Răsfoiți Sursa

正在重构语言相关的内容

Signed-off-by: 716 <[email protected]>
716 4 ani în urmă
părinte
comite
b751eb5b34
32 a modificat fișierele cu 859 adăugiri și 813 ștergeri
  1. 7 5
      internal/ifaces/iSubFormatter.go
  2. 17 16
      internal/logic/emby_helper/embyhelper.go
  3. 26 0
      internal/logic/emby_helper/embyhelper_test.go
  4. 12 13
      internal/logic/sub_parser/ass/ass_test.go
  5. 5 5
      internal/logic/sub_parser/srt/srt_test.go
  6. 2 1
      internal/logic/sub_supplier/shooter/shooter.go
  7. 3 2
      internal/logic/sub_supplier/subhd/subhd.go
  8. 3 3
      internal/logic/sub_supplier/xunlei/xunlei.go
  9. 4 3
      internal/logic/sub_supplier/zimuku/zimuku.go
  10. 2 2
      internal/logic/sub_timeline_fixer/sub_timeline_fixer_helper.go
  11. 2 2
      internal/pkg/ffmpeg_helper/audio_info.go
  12. 2 2
      internal/pkg/ffmpeg_helper/subtitile_info.go
  13. 44 0
      internal/pkg/language/ISOLanguage.go
  14. 11 0
      internal/pkg/language/instance.go
  15. 0 526
      internal/pkg/language/language.go
  16. 185 0
      internal/pkg/language/my_language.go
  17. 47 0
      internal/pkg/language/string_encoding.go
  18. 225 0
      internal/pkg/language/whatlanggo.go
  19. 13 13
      internal/pkg/sub_formatter/emby/emby.go
  20. 13 13
      internal/pkg/sub_formatter/emby/emby_test.go
  21. 12 12
      internal/pkg/sub_formatter/normal/normal.go
  22. 10 10
      internal/pkg/sub_formatter/normal/normal_test.go
  23. 37 37
      internal/pkg/sub_formatter/old/old.go
  24. 5 5
      internal/pkg/sub_formatter/sub_format_changer.go
  25. 5 5
      internal/pkg/sub_helper/sub_helper.go
  26. 0 110
      internal/types/language.go
  27. 43 0
      internal/types/language/ISOLanguage.go
  28. 26 0
      internal/types/language/language.go
  29. 66 0
      internal/types/language/my_language.go
  30. 2 2
      internal/types/series/info.go
  31. 14 12
      internal/types/subparser/fileinfo.go
  32. 16 14
      internal/types/supplier/subinfo.go

+ 7 - 5
internal/ifaces/iSubFormatter.go

@@ -1,6 +1,8 @@
 package ifaces
 
-import "github.com/allanpk716/ChineseSubFinder/internal/types"
+import (
+	"github.com/allanpk716/ChineseSubFinder/internal/types/language"
+)
 
 // ISubFormatter 如果新增了更多的字幕命名格式化的实现,需要找所有以下 to do 去增加实现
 // TODO 如果字幕格式新增了实现,这里也需要添加对应的实例
@@ -9,10 +11,10 @@ type ISubFormatter interface {
 	GetFormatterName() string
 	// GetFormatterFormatterName 需要转换为 FormatterName 使用
 	GetFormatterFormatterName() int
-	// IsMatchThisFormat 是否满足当前实现接口的字幕命名格式 - 是否符合规则、fileNameWithOutExt string, subExt string, subLang types.Language, extraSubPreName string
-	IsMatchThisFormat(subName string) (bool, string, string, types.Language, string)
+	// IsMatchThisFormat 是否满足当前实现接口的字幕命名格式 - 是否符合规则、fileNameWithOutExt string, subExt string, subLang types.MyLanguage, extraSubPreName string
+	IsMatchThisFormat(subName string) (bool, string, string, language.MyLanguage, string)
 	// GenerateMixSubName 通过视频和字幕信息,生成当前实现接口的字幕命名格式。extraSubPreName 一般是填写字幕网站,不填写则留空 - 新名称、新名称带有 default 标记,新名称带有 forced 标记
-	GenerateMixSubName(videoFileName, subExt string, subLang types.Language, extraSubPreName string) (string, string, string)
+	GenerateMixSubName(videoFileName, subExt string, subLang language.MyLanguage, extraSubPreName string) (string, string, string)
 	// GenerateMixSubNameBase 通过没有后缀名信息的文件名,生成当前实现接口的字幕命名格式。extraSubPreName 一般是填写字幕网站,不填写则留空 - 新名称、新名称带有 default 标记,新名称带有 forced 标记
-	GenerateMixSubNameBase(fileNameWithOutExt, subExt string, subLang types.Language, extraSubPreName string) (string, string, string)
+	GenerateMixSubNameBase(fileNameWithOutExt, subExt string, subLang language.MyLanguage, extraSubPreName string) (string, string, string)
 }

+ 17 - 16
internal/logic/emby_helper/embyhelper.go

@@ -5,8 +5,8 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/common"
 	embyHelper "github.com/allanpk716/ChineseSubFinder/internal/pkg/emby_api"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
-	"github.com/allanpk716/ChineseSubFinder/internal/types"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/emby"
+	"github.com/allanpk716/ChineseSubFinder/internal/types/language"
 	"github.com/panjf2000/ants/v2"
 	"golang.org/x/net/context"
 	"path"
@@ -337,12 +337,12 @@ func (em *EmbyHelper) GetInternalEngSubAndExChineseEnglishSub(videoId string) (b
 			if em.subTypeStringOK(stream.Codec) == true &&
 				em.langStringOK(stream.Language) == true &&
 				// 只支持 简英、繁英
-				(strings.Contains(stream.Language, types.MatchLangChsEn) == true || strings.Contains(stream.Language, types.MatchLangChtEn) == true) {
+				(strings.Contains(stream.Language, language.MatchLangChsEn) == true || strings.Contains(stream.Language, language.MatchLangChtEn) == true) {
 
 				tmpFileName := filepath.Base(stream.Path)
 				// 去除 .default 或者 .forced
-				tmpFileName = strings.ReplaceAll(tmpFileName, types.Sub_Ext_Mark_Default, "")
-				tmpFileName = strings.ReplaceAll(tmpFileName, types.Sub_Ext_Mark_Forced, "")
+				tmpFileName = strings.ReplaceAll(tmpFileName, language.Sub_Ext_Mark_Default, "")
+				tmpFileName = strings.ReplaceAll(tmpFileName, language.Sub_Ext_Mark_Forced, "")
 				tmpFileNameWithOutExt = strings.ReplaceAll(tmpFileName, path.Ext(tmpFileName), "")
 				exSubList = append(exSubList, *emby.NewSubInfo(tmpFileNameWithOutExt+"."+stream.Codec, "."+stream.Codec, stream.Index))
 			} else {
@@ -411,7 +411,7 @@ func (em *EmbyHelper) GetInternalEngSubAndExChineseEnglishSub(videoId string) (b
 	return true, inSubList, exSubList, nil
 }
 
-// langStringOK 从 Emby api 拿到字幕的 Language string是否是符合本程序要求的
+// langStringOK 从 Emby api 拿到字幕的 MyLanguage string是否是符合本程序要求的
 func (em *EmbyHelper) langStringOK(inLang string) bool {
 
 	tmpString := strings.ToLower(inLang)
@@ -427,18 +427,19 @@ func (em *EmbyHelper) langStringOK(inLang string) bool {
 		}
 	}
 	switch nextString {
-	case em.replaceLangString(types.Emby_chi),
-		em.replaceLangString(types.Emby_chn),
-		em.replaceLangString(types.Emby_chs),
-		em.replaceLangString(types.Emby_cht),
-		em.replaceLangString(types.Emby_chs_en),
-		em.replaceLangString(types.Emby_cht_en),
-		em.replaceLangString(types.Emby_chs_jp),
-		em.replaceLangString(types.Emby_cht_jp),
-		em.replaceLangString(types.Emby_chs_kr),
-		em.replaceLangString(types.Emby_cht_kr):
+	// 早期版本支持的语言类型,现在弃用
+	case em.replaceLangString(language.Emby_chi),
+		em.replaceLangString(language.Emby_chn),
+		em.replaceLangString(language.Emby_chs),
+		em.replaceLangString(language.Emby_cht),
+		em.replaceLangString(language.Emby_chs_en),
+		em.replaceLangString(language.Emby_cht_en),
+		em.replaceLangString(language.Emby_chs_jp),
+		em.replaceLangString(language.Emby_cht_jp),
+		em.replaceLangString(language.Emby_chs_kr),
+		em.replaceLangString(language.Emby_cht_kr):
 		return true
-	case em.replaceLangString(types.Emby_chinese):
+	case em.replaceLangString(language.Emby_chinese):
 		return true
 	default:
 		return false

+ 26 - 0
internal/logic/emby_helper/embyhelper_test.go

@@ -42,3 +42,29 @@ func TestEmbyHelper_GetInternalEngSubAndExSub(t *testing.T) {
 
 	println(internalEngSub[0].FileName, exCh_EngSub[0].FileName)
 }
+
+func TestEmbyHelper_langStringOK(t *testing.T) {
+
+	type args struct {
+		inLang string
+	}
+
+	config := config.GetConfig()
+	em := NewEmbyHelper(config.EmbyConfig)
+
+	tests := []struct {
+		name string
+		args args
+		want bool
+	}{
+		{name: "00", args: args{inLang: "chinese(简英,subhd)"}, want: true},
+		{name: "01", args: args{inLang: "chinese(简英,xunlei)"}, want: true},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := em.langStringOK(tt.args.inLang); got != tt.want {
+				t.Errorf("langStringOK() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}

+ 12 - 13
internal/logic/sub_parser/ass/ass_test.go

@@ -2,8 +2,7 @@ package ass
 
 import (
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg"
-	"github.com/allanpk716/ChineseSubFinder/internal/types"
-	"path"
+	"github.com/allanpk716/ChineseSubFinder/internal/types/language"
 	"testing"
 )
 
@@ -23,19 +22,19 @@ func TestParser_DetermineFileTypeFromFile(t *testing.T) {
 		args     args
 		wantNil  bool
 		wantErr  bool
-		wantLang types.Language
+		wantLang language.MyLanguage
 	}{
-		{name: "1", args: args{filePath: filepath.Join(testRootDir, "[xunlei]_0_C3A5CUsers5CAdministrator5CDesktop5CThe Boss Baby Family Business_S0E0.ass")}, wantNil: false, wantErr: false, wantLang: types.ChineseSimpleEnglish},
-		{name: "2", args: args{filePath: filepath.Join(testRootDir, "Loki - S01E01 - Glorious Purpose WEBDL-1080p Proper.chs[subhd].ass")}, wantNil: false, wantErr: false, wantLang: types.ChineseSimpleEnglish},
-		{name: "3", args: args{filePath: filepath.Join(testRootDir, "oslo.2021.1080p.web.h264-naisu.简体&英文.ass")}, wantNil: false, wantErr: false, wantLang: types.ChineseSimpleEnglish},
-		{name: "4", args: args{filePath: filepath.Join(testRootDir, "oslo.2021.1080p.web.h264-naisu.繁体&英文.ass")}, wantNil: false, wantErr: false, wantLang: types.ChineseTraditionalEnglish},
-		{name: "5", args: args{filePath: filepath.Join(testRootDir, "oslo.2021.1080p.web.h264-naisu.繁体.ass")}, wantNil: false, wantErr: false, wantLang: types.ChineseTraditional},
+		{name: "1", args: args{filePath: filepath.Join(testRootDir, "[xunlei]_0_C3A5CUsers5CAdministrator5CDesktop5CThe Boss Baby Family Business_S0E0.ass")}, wantNil: false, wantErr: false, wantLang: language.ChineseSimpleEnglish},
+		{name: "2", args: args{filePath: filepath.Join(testRootDir, "Loki - S01E01 - Glorious Purpose WEBDL-1080p Proper.chs[subhd].ass")}, wantNil: false, wantErr: false, wantLang: language.ChineseSimpleEnglish},
+		{name: "3", args: args{filePath: filepath.Join(testRootDir, "oslo.2021.1080p.web.h264-naisu.简体&英文.ass")}, wantNil: false, wantErr: false, wantLang: language.ChineseSimpleEnglish},
+		{name: "4", args: args{filePath: filepath.Join(testRootDir, "oslo.2021.1080p.web.h264-naisu.繁体&英文.ass")}, wantNil: false, wantErr: false, wantLang: language.ChineseTraditionalEnglish},
+		{name: "5", args: args{filePath: filepath.Join(testRootDir, "oslo.2021.1080p.web.h264-naisu.繁体.ass")}, wantNil: false, wantErr: false, wantLang: language.ChineseTraditional},
 		// 特殊一点的字幕
-		{name: "6", args: args{filePath: filepath.Join(testRootDir, "SP-Antebellum.1080p.WEB-DL.DD5.1.H.264-EVO.zh.ass")}, wantNil: false, wantErr: false, wantLang: types.ChineseSimpleEnglish},
-		{name: "7", args: args{filePath: filepath.Join(testRootDir, "SP-Gunpowder.Milkshake.2021.1080p.WEB.h264-RUMOUR[rarbg].chinese(简).ass")}, wantNil: false, wantErr: false, wantLang: types.ChineseSimpleEnglish},
-		{name: "8", args: args{filePath: filepath.Join(testRootDir, "SP-One.Hundred.And.One.Dalmatians.1961.1080p.BluRay.x264.AAC5.1-[YTS.LT].zh-cn.ass")}, wantNil: false, wantErr: false, wantLang: types.ChineseSimpleEnglish},
-		{name: "9", args: args{filePath: filepath.Join(testRootDir, "SP-Pirates.of.the.Caribbean.The.Curse.of.the.Black.Pearl.2003.BluRay.1080p.x265.10bit.2Audio.MNHD-FRDS.zh-cn.ssa")}, wantNil: false, wantErr: false, wantLang: types.ChineseSimpleEnglish},
-		{name: "10", args: args{filePath: filepath.Join(testRootDir, "SP-Schindlers.List.1993.BluRay.1080p.x265.10bit.2Audio.MNHD-FRDS.zh-cn.ass")}, wantNil: false, wantErr: false, wantLang: types.ChineseSimpleEnglish},
+		{name: "6", args: args{filePath: filepath.Join(testRootDir, "SP-Antebellum.1080p.WEB-DL.DD5.1.H.264-EVO.zh.ass")}, wantNil: false, wantErr: false, wantLang: language.ChineseSimpleEnglish},
+		{name: "7", args: args{filePath: filepath.Join(testRootDir, "SP-Gunpowder.Milkshake.2021.1080p.WEB.h264-RUMOUR[rarbg].chinese(简).ass")}, wantNil: false, wantErr: false, wantLang: language.ChineseSimpleEnglish},
+		{name: "8", args: args{filePath: filepath.Join(testRootDir, "SP-One.Hundred.And.One.Dalmatians.1961.1080p.BluRay.x264.AAC5.1-[YTS.LT].zh-cn.ass")}, wantNil: false, wantErr: false, wantLang: language.ChineseSimpleEnglish},
+		{name: "9", args: args{filePath: filepath.Join(testRootDir, "SP-Pirates.of.the.Caribbean.The.Curse.of.the.Black.Pearl.2003.BluRay.1080p.x265.10bit.2Audio.MNHD-FRDS.zh-cn.ssa")}, wantNil: false, wantErr: false, wantLang: language.ChineseSimpleEnglish},
+		{name: "10", args: args{filePath: filepath.Join(testRootDir, "SP-Schindlers.List.1993.BluRay.1080p.x265.10bit.2Audio.MNHD-FRDS.zh-cn.ass")}, wantNil: false, wantErr: false, wantLang: language.ChineseSimpleEnglish},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {

+ 5 - 5
internal/logic/sub_parser/srt/srt_test.go

@@ -2,7 +2,7 @@ package srt
 
 import (
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg"
-	"github.com/allanpk716/ChineseSubFinder/internal/types"
+	"github.com/allanpk716/ChineseSubFinder/internal/types/language"
 	"path/filepath"
 	"testing"
 )
@@ -22,11 +22,11 @@ func TestParser_DetermineFileType(t *testing.T) {
 		args     args
 		wantNil  bool
 		wantErr  bool
-		wantLang types.Language
+		wantLang language.MyLanguage
 	}{
-		{name: "1", args: args{filePath: filepath.Join(testRootDir, "[zimuku]_5_Loki.S01E02.The.Variant.1080p.DSNP.WEB-DL.DDP5.1.Atmos.H.264-CM.chs&eng.srt")}, wantNil: false, wantErr: false, wantLang: types.ChineseSimpleEnglish},
-		{name: "2", args: args{filePath: filepath.Join(testRootDir, "[zimuku]_5_Loki.S01E03.Lamentis.1080p.DSNP.WEB-DL.DDP5.1.H.264-TOMMY.chs&eng.srt")}, wantNil: false, wantErr: false, wantLang: types.ChineseSimpleEnglish},
-		{name: "3", args: args{filePath: filepath.Join(testRootDir, "Bridge of Spies (2015) (1080p BluRay x265 Silence).zh-cn.srt")}, wantNil: false, wantErr: false, wantLang: types.ChineseSimpleEnglish},
+		{name: "1", args: args{filePath: filepath.Join(testRootDir, "[zimuku]_5_Loki.S01E02.The.Variant.1080p.DSNP.WEB-DL.DDP5.1.Atmos.H.264-CM.chs&eng.srt")}, wantNil: false, wantErr: false, wantLang: language.ChineseSimpleEnglish},
+		{name: "2", args: args{filePath: filepath.Join(testRootDir, "[zimuku]_5_Loki.S01E03.Lamentis.1080p.DSNP.WEB-DL.DDP5.1.H.264-TOMMY.chs&eng.srt")}, wantNil: false, wantErr: false, wantLang: language.ChineseSimpleEnglish},
+		{name: "3", args: args{filePath: filepath.Join(testRootDir, "Bridge of Spies (2015) (1080p BluRay x265 Silence).zh-cn.srt")}, wantNil: false, wantErr: false, wantLang: language.ChineseSimpleEnglish},
 		// 特殊一点的字幕
 		// 这一个不确定是什么类型的字幕
 		//{name: "4", args: args{filePath: filepath.Join(testRootDir, "SP-Empire.Of.Dreams.The.Story.Of.The.Star.Wars.Trilogy.2004.1080p.BluRay.x264.AAC5.1-[YTS.MX].zh-cn.srt")}, wantNil: false, wantErr: false, wantLang: types.ChineseSimple},

+ 2 - 1
internal/logic/sub_supplier/shooter/shooter.go

@@ -7,6 +7,7 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/types"
+	"github.com/allanpk716/ChineseSubFinder/internal/types/language"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/series"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/supplier"
 	"github.com/sirupsen/logrus"
@@ -100,7 +101,7 @@ func (s Supplier) getSubListFromFile(filePath string) ([]supplier.SubInfo, error
 				continue
 			}
 
-			onSub := supplier.NewSubInfo(s.GetSupplierName(), int64(i), fileName, types.ChineseSimple, file.Link, 0, shooter.Delay, subExt, data)
+			onSub := supplier.NewSubInfo(s.GetSupplierName(), int64(i), fileName, language.ChineseSimple, file.Link, 0, shooter.Delay, subExt, data)
 			outSubInfoList = append(outSubInfoList, *onSub)
 			// 如果够了那么多个字幕就返回
 			if len(outSubInfoList) >= s.topic {

+ 3 - 2
internal/logic/sub_supplier/subhd/subhd.go

@@ -13,6 +13,7 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/rod_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_parser_hub"
 	"github.com/allanpk716/ChineseSubFinder/internal/types"
+	"github.com/allanpk716/ChineseSubFinder/internal/types/language"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/series"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/supplier"
 	"github.com/go-rod/rod"
@@ -126,7 +127,7 @@ func (s Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]su
 			s.log.Errorln("subhd step2Ex", err)
 			continue
 		}
-		oneSubInfo := supplier.NewSubInfo(s.GetSupplierName(), int64(i), hdContent.Filename, types.ChineseSimple, pkg.AddBaseUrl(common.SubSubHDRootUrl, item.Url), 0,
+		oneSubInfo := supplier.NewSubInfo(s.GetSupplierName(), int64(i), hdContent.Filename, language.ChineseSimple, pkg.AddBaseUrl(common.SubSubHDRootUrl, item.Url), 0,
 			0, hdContent.Ext, hdContent.Data)
 		oneSubInfo.Season = item.Season
 		oneSubInfo.Episode = item.Episode
@@ -218,7 +219,7 @@ func (s Supplier) getSubListFromKeyword4Movie(keyword string) ([]supplier.SubInf
 			s.log.Errorln("subhd step2Ex", err)
 			return nil, err
 		}
-		subInfos = append(subInfos, *supplier.NewSubInfo(s.GetSupplierName(), int64(i), hdContent.Filename, types.ChineseSimple, pkg.AddBaseUrl(common.SubSubHDRootUrl, item.Url), 0, 0, hdContent.Ext, hdContent.Data))
+		subInfos = append(subInfos, *supplier.NewSubInfo(s.GetSupplierName(), int64(i), hdContent.Filename, language.ChineseSimple, pkg.AddBaseUrl(common.SubSubHDRootUrl, item.Url), 0, 0, hdContent.Ext, hdContent.Data))
 	}
 
 	return subInfos, nil

+ 3 - 3
internal/logic/sub_supplier/xunlei/xunlei.go

@@ -82,7 +82,7 @@ func (s Supplier) getSubListFromFile(filePath string) ([]supplier.SubInfo, error
 	for _, v := range jsonList.Sublist {
 		if len(v.Scid) > 0 && v.Scid != "" {
 			// 符合中文语言的先加入列表
-			tmpLang := language.LangConverter(v.Language)
+			tmpLang := language.LangConverter4Sub_Supplier(v.Language)
 			if language.HasChineseLang(tmpLang) == true && sub_parser_hub.IsSubTypeWanted(v.Sname) == true {
 				tmpXunLeiSubListChinese = append(tmpXunLeiSubListChinese, v)
 			}
@@ -96,7 +96,7 @@ func (s Supplier) getSubListFromFile(filePath string) ([]supplier.SubInfo, error
 				break
 			}
 			if len(v.Scid) > 0 && v.Scid != "" {
-				tmpLang := language.LangConverter(v.Language)
+				tmpLang := language.LangConverter4Sub_Supplier(v.Language)
 				if language.HasChineseLang(tmpLang) == false {
 					tmpXunLeiSubListChinese = append(tmpXunLeiSubListChinese, v)
 				}
@@ -105,7 +105,7 @@ func (s Supplier) getSubListFromFile(filePath string) ([]supplier.SubInfo, error
 	}
 	// 再开始下载字幕
 	for i, v := range tmpXunLeiSubListChinese {
-		tmpLang := language.LangConverter(v.Language)
+		tmpLang := language.LangConverter4Sub_Supplier(v.Language)
 		data, filename, err := pkg.DownFile(v.Surl)
 		if err != nil {
 			s.log.Errorln("xunlei pkg.DownFile:", err)

+ 4 - 3
internal/logic/sub_supplier/zimuku/zimuku.go

@@ -12,6 +12,7 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/notify_center"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_parser_hub"
 	"github.com/allanpk716/ChineseSubFinder/internal/types"
+	language2 "github.com/allanpk716/ChineseSubFinder/internal/types/language"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/series"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/supplier"
 	"github.com/sirupsen/logrus"
@@ -249,7 +250,7 @@ func (s Supplier) whichSubInfoNeedDownload(subInfos SubInfos, err error) []suppl
 	// 首先过滤出中文的字幕,同时需要满足是支持的字幕
 	var tmpSubInfo = make([]SubInfo, 0)
 	for _, subInfo := range subInfos {
-		tmpLang := language.LangConverter(subInfo.Lang)
+		tmpLang := language.LangConverter4Sub_Supplier(subInfo.Lang)
 		if language.HasChineseLang(tmpLang) == true && sub_parser_hub.IsSubTypeWanted(subInfo.Ext) == true {
 			tmpSubInfo = append(tmpSubInfo, subInfo)
 		}
@@ -260,7 +261,7 @@ func (s Supplier) whichSubInfoNeedDownload(subInfos SubInfos, err error) []suppl
 			if len(tmpSubInfo) >= s.topic {
 				break
 			}
-			tmpLang := language.LangConverter(subInfo.Lang)
+			tmpLang := language.LangConverter4Sub_Supplier(subInfo.Lang)
 			if language.HasChineseLang(tmpLang) == false {
 				tmpSubInfo = append(tmpSubInfo, subInfo)
 			}
@@ -276,7 +277,7 @@ func (s Supplier) whichSubInfoNeedDownload(subInfos SubInfos, err error) []suppl
 		}
 		// 默认都是包含中文字幕的,然后具体使用的时候再进行区分
 
-		oneSubInfo := supplier.NewSubInfo(s.GetSupplierName(), int64(i), fileName, types.ChineseSimple, pkg.AddBaseUrl(common.SubZiMuKuRootUrl, subInfo.SubDownloadPageUrl), 0,
+		oneSubInfo := supplier.NewSubInfo(s.GetSupplierName(), int64(i), fileName, language2.ChineseSimple, pkg.AddBaseUrl(common.SubZiMuKuRootUrl, subInfo.SubDownloadPageUrl), 0,
 			0, filepath.Ext(fileName), data)
 
 		oneSubInfo.Season = subInfo.Season

+ 2 - 2
internal/logic/sub_timeline_fixer/sub_timeline_fixer_helper.go

@@ -15,8 +15,8 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_parser_hub"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_timeline_fixer"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/vad"
-	"github.com/allanpk716/ChineseSubFinder/internal/types"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/emby"
+	"github.com/allanpk716/ChineseSubFinder/internal/types/language"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/sub_timeline_fiexer"
 	"os"
 	"path"
@@ -275,7 +275,7 @@ func (s SubTimelineFixerHelper) fixSubTimeline(enSubFile emby.SubInfo, ch_enSubF
 		}
 		// 是否包含 default 关键词,暂时无需判断 forced
 		hasDefault := false
-		if strings.Contains(strings.ToLower(infoSrc.Name), types.Sub_Ext_Mark_Default) == true {
+		if strings.Contains(strings.ToLower(infoSrc.Name), language.Sub_Ext_Mark_Default) == true {
 			hasDefault = true
 		}
 		// 生成对应字幕命名格式的,字幕命名。这里注意,normal 的时候, extraSubName+"-fix" 是无效的,不会被设置,也就是直接覆盖之前的字幕了。

+ 2 - 2
internal/pkg/ffmpeg_helper/audio_info.go

@@ -3,7 +3,7 @@ package ffmpeg_helper
 import (
 	"fmt"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/language"
-	"github.com/allanpk716/ChineseSubFinder/internal/types"
+	language2 "github.com/allanpk716/ChineseSubFinder/internal/types/language"
 )
 
 type AudioInfo struct {
@@ -28,7 +28,7 @@ func NewAudioInfo(index int, codecName, codecType, timeBase, startTime, language
 }
 
 // GetLanguage 获取音频的语言类型
-func (a AudioInfo) GetLanguage() types.Language {
+func (a AudioInfo) GetLanguage() language2.MyLanguage {
 	return language.ISOString2SupportLang(a.language)
 }
 

+ 2 - 2
internal/pkg/ffmpeg_helper/subtitile_info.go

@@ -3,7 +3,7 @@ package ffmpeg_helper
 import (
 	"fmt"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/language"
-	"github.com/allanpk716/ChineseSubFinder/internal/types"
+	language2 "github.com/allanpk716/ChineseSubFinder/internal/types/language"
 )
 
 type SubtitleInfo struct {
@@ -39,7 +39,7 @@ func (s *SubtitleInfo) SetContent(content string) error {
 }
 
 // GetLanguage 获取字幕语言的类型
-func (s SubtitleInfo) GetLanguage() types.Language {
+func (s SubtitleInfo) GetLanguage() language2.MyLanguage {
 	return language.ISOString2SupportLang(s.language)
 }
 

+ 44 - 0
internal/pkg/language/ISOLanguage.go

@@ -0,0 +1,44 @@
+package language
+
+import (
+	"github.com/allanpk716/ChineseSubFinder/internal/types/language"
+	"strings"
+)
+
+// ChineseISOString2Lang 将 中文描述:zh、zho、chi 转换为 types.MyLanguage
+func ChineseISOString2Lang(chineseStr string) language.MyLanguage {
+
+	switch chineseStr {
+	case language.ISO_639_1_Chinese, language.ISO_639_2T_Chinese, language.ISO_639_2B_Chinese:
+		return language.ChineseSimple
+	default:
+		return language.Unknown
+	}
+}
+
+// ISOString2SupportLang 从 639-2/B 的语言缩写字符串转换为内部的 MyLanguage 类型,值支持
+// https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
+func ISOString2SupportLang(isoString string) language.MyLanguage {
+	switch strings.ToLower(isoString) {
+	case language.ISO_639_2B_Chinese:
+		return language.ChineseSimple
+	case language.ISO_639_2B_English:
+		return language.English
+	case language.ISO_639_2B_Japanese:
+		return language.Japanese
+	case language.ISO_639_2B_Korean:
+		return language.Korean
+	default:
+		return language.Unknown
+	}
+}
+
+// IsSupportISOString 是否是受支持的  639-2/B 语言,中、英、日、韩
+func IsSupportISOString(isoString string) bool {
+	switch strings.ToLower(isoString) {
+	case language.ISO_639_2B_Chinese, language.ISO_639_2B_English, language.ISO_639_2B_Japanese, language.ISO_639_2B_Korean:
+		return true
+	default:
+		return false
+	}
+}

+ 11 - 0
internal/pkg/language/instance.go

@@ -0,0 +1,11 @@
+package language
+
+import (
+	"github.com/go-creed/sat"
+	"github.com/saintfish/chardet"
+)
+
+var (
+	chDict   = sat.DefaultDict()
+	detector = chardet.NewTextDetector()
+)

+ 0 - 526
internal/pkg/language/language.go

@@ -1,526 +0,0 @@
-package language
-
-import (
-	"github.com/abadojack/whatlanggo"
-	"github.com/allanpk716/ChineseSubFinder/internal/logic/charset"
-	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
-	"github.com/allanpk716/ChineseSubFinder/internal/types"
-	"github.com/allanpk716/ChineseSubFinder/internal/types/subparser"
-	"github.com/axgle/mahonia"
-	"github.com/go-creed/sat"
-	nzlov "github.com/nzlov/chardet"
-	"github.com/saintfish/chardet"
-	"strings"
-)
-
-// LangConverter 语言转换器
-func LangConverter(subLang string) types.Language {
-	/*
-		xunlei:未知语言、简体&英语、繁体&英语、简体、繁体、英语
-	*/
-	if strings.Contains(subLang, types.MatchLangDouble) {
-		// 双语 - 简英
-		return types.ChineseSimpleEnglish
-	} else if strings.Contains(subLang, types.MatchLangChs) {
-		// 优先简体
-		if strings.Contains(subLang, types.MatchLangEn) {
-			// 简英
-			return types.ChineseSimpleEnglish
-		} else if strings.Contains(subLang, types.MatchLangJp) {
-			// 简日
-			return types.ChineseSimpleJapanese
-		} else if strings.Contains(subLang, types.MatchLangKr) {
-			// 简韩
-			return types.ChineseSimpleKorean
-		}
-		// 默认简体中文
-		return types.ChineseSimple
-	} else if strings.Contains(subLang, types.MatchLangCht) {
-		// 然后是繁体
-		if strings.Contains(subLang, types.MatchLangEn) {
-			// 繁英
-			return types.ChineseTraditionalEnglish
-		} else if strings.Contains(subLang, types.MatchLangJp) {
-			// 繁日
-			return types.ChineseTraditionalJapanese
-		} else if strings.Contains(subLang, types.MatchLangKr) {
-			// 繁韩
-			return types.ChineseTraditionalKorean
-		}
-		// 默认繁体中文
-		return types.ChineseTraditional
-	} else if strings.Contains(subLang, types.MatchLangEn) {
-		// 英文
-		return types.English
-	} else if strings.Contains(subLang, types.MatchLangJp) {
-		// 日文
-		return types.Japanese
-	} else if strings.Contains(subLang, types.MatchLangKr) {
-		// 韩文
-		return types.Korean
-	} else {
-		// 都没有,则标记未知
-		return types.Unknow
-	}
-}
-
-// HasChineseLang 是否包含中文
-func HasChineseLang(lan types.Language) bool {
-	switch lan {
-	case types.ChineseSimple,
-		types.ChineseTraditional,
-
-		types.ChineseSimpleEnglish,
-		types.ChineseTraditionalEnglish,
-
-		types.ChineseSimpleJapanese,
-		types.ChineseTraditionalJapanese,
-
-		types.ChineseSimpleKorean,
-		types.ChineseTraditionalKorean:
-		return true
-	default:
-		return false
-	}
-}
-
-// IsBilingualSubtitle 是否是双语字幕
-func IsBilingualSubtitle(lan types.Language) bool {
-	switch lan {
-	case types.ChineseSimpleEnglish,
-		types.ChineseTraditionalEnglish,
-
-		types.ChineseSimpleJapanese,
-		types.ChineseTraditionalJapanese,
-
-		types.ChineseSimpleKorean,
-		types.ChineseTraditionalKorean:
-		return true
-	default:
-		return false
-	}
-}
-
-// Lang2EmbyNameOld 弃用。从语言转换到 Emby 能够识别的字幕命名
-func Lang2EmbyNameOld(lan types.Language) string {
-	switch lan {
-	case types.Unknow: // 未知语言
-		return types.Emby_unknow
-	case types.ChineseSimple: // 简体中文
-		return types.Emby_chs
-	case types.ChineseTraditional: // 繁体中文
-		return types.Emby_cht
-	case types.ChineseSimpleEnglish: // 简英双语字幕
-		return types.Emby_chs_en
-	case types.ChineseTraditionalEnglish: // 繁英双语字幕
-		return types.Emby_cht_en
-	case types.English: // 英文
-		return types.Emby_en
-	case types.Japanese: // 日语
-		return types.Emby_jp
-	case types.ChineseSimpleJapanese: // 简日双语字幕
-		return types.Emby_chs_jp
-	case types.ChineseTraditionalJapanese: // 繁日双语字幕
-		return types.Emby_cht_jp
-	case types.Korean: // 韩语
-		return types.Emby_kr
-	case types.ChineseSimpleKorean: // 简韩双语字幕
-		return types.Emby_chs_kr
-	case types.ChineseTraditionalKorean: // 繁韩双语字幕
-		return types.Emby_cht_kr
-	default:
-		return types.Emby_unknow
-	}
-}
-
-// Lang2ChineseString 将 types.Language 转换为中文描述:简、繁、简英
-func Lang2ChineseString(lan types.Language) string {
-	switch lan {
-	case types.Unknow: // 未知语言
-		return types.MathLangChnUnknow
-	case types.ChineseSimple: // 简体中文
-		return types.MatchLangChs
-	case types.ChineseTraditional: // 繁体中文
-		return types.MatchLangCht
-	case types.ChineseSimpleEnglish: // 简英双语字幕
-		return types.MatchLangChsEn
-	case types.ChineseTraditionalEnglish: // 繁英双语字幕
-		return types.MatchLangChtEn
-	case types.English: // 英文
-		return types.MatchLangEn
-	case types.Japanese: // 日语
-		return types.MatchLangJp
-	case types.ChineseSimpleJapanese: // 简日双语字幕
-		return types.MatchLangChsJp
-	case types.ChineseTraditionalJapanese: // 繁日双语字幕
-		return types.MatchLangChtJp
-	case types.Korean: // 韩语
-		return types.MatchLangKr
-	case types.ChineseSimpleKorean: // 简韩双语字幕
-		return types.MatchLangChsKr
-	case types.ChineseTraditionalKorean: // 繁韩双语字幕
-		return types.MatchLangChtKr
-	default:
-		return types.MathLangChnUnknow
-	}
-}
-
-// ChineseISOString2Lang 将 中文描述:zh、zho、chi 转换为 types.Language
-func ChineseISOString2Lang(chineseStr string) types.Language {
-
-	switch chineseStr {
-	case types.ChineseAbbr_639_1, types.ChineseAbbr_639_2T, types.ChineseAbbr_639_2B:
-		return types.ChineseSimple
-	default:
-		return types.Unknow
-	}
-}
-
-// ISOString2SupportLang 从 639-2/B 的语言缩写字符串转换为内部的 Language 类型,值支持
-// https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
-func ISOString2SupportLang(isoString string) types.Language {
-	switch strings.ToLower(isoString) {
-	case types.Lang_639_2B_Chinese:
-		return types.ChineseSimple
-	case types.Lang_639_2B_English:
-		return types.English
-	case types.Lang_639_2B_Japan:
-		return types.Japanese
-	case types.Lang_639_2B_Korean:
-		return types.Korean
-	default:
-		return types.Unknow
-	}
-}
-
-// IsSupportISOString 是否是受支持的  639-2/B 语言,中、英、日、韩
-func IsSupportISOString(isoString string) bool {
-	switch strings.ToLower(isoString) {
-	case types.Lang_639_2B_Chinese, types.Lang_639_2B_English, types.Lang_639_2B_Japan, types.Lang_639_2B_Korean:
-		return true
-	default:
-		return false
-	}
-}
-
-// ChineseString2Lang 将 中文描述:简、繁、简英 转换为 types.Language
-func ChineseString2Lang(chineseStr string) types.Language {
-	switch chineseStr {
-	case types.MathLangChnUnknow: // 未知语言
-		return types.Unknow
-	case types.MatchLangChs: // 简体中文
-		return types.ChineseSimple
-	case types.MatchLangCht: // 繁体中文
-		return types.ChineseTraditional
-	case types.MatchLangChsEn: // 简英双语字幕
-		return types.ChineseSimpleEnglish
-	case types.MatchLangChtEn: // 繁英双语字幕
-		return types.ChineseTraditionalEnglish
-	case types.MatchLangEn: // 英文
-		return types.English
-	case types.MatchLangJp: // 日语
-		return types.Japanese
-	case types.MatchLangChsJp: // 简日双语字幕
-		return types.ChineseSimpleJapanese
-	case types.MatchLangChtJp: // 繁日双语字幕
-		return types.ChineseTraditionalJapanese
-	case types.MatchLangKr: // 韩语
-		return types.Korean
-	case types.MatchLangChsKr: // 简韩双语字幕
-		return types.ChineseSimpleKorean
-	case types.MatchLangChtKr: // 繁韩双语字幕
-		return types.ChineseTraditionalKorean
-	default:
-		return types.Unknow
-	}
-}
-
-// GetLangOptions 语言识别的 Options Whitelist
-func GetLangOptions() whatlanggo.Options {
-	return whatlanggo.Options{
-		Whitelist: map[whatlanggo.Lang]bool{
-			whatlanggo.Cmn: true, // 中文	11
-			whatlanggo.Eng: true, // 英文	15
-			whatlanggo.Jpn: true, // 日文	32
-			whatlanggo.Kor: true, // 韩文	37
-		},
-	}
-}
-
-// IsWhiteListLang 是否是白名单语言
-func IsWhiteListLang(lang whatlanggo.Lang) bool {
-	switch lang {
-	// 中文 英文 日文 韩文
-	case whatlanggo.Cmn, whatlanggo.Eng, whatlanggo.Jpn, whatlanggo.Kor:
-		return true
-	default:
-		return false
-	}
-}
-
-// DetectSubLangAndStatistics 检测语言然后统计
-func DetectSubLangAndStatistics(oneDialogue subparser.OneDialogue, langDict map[int]int, usefulDialoguseEx *[]subparser.OneDialogueEx, chLines *[]string, otherLines *[]string) {
-
-	var oneDialogueEx subparser.OneDialogueEx
-	oneDialogueEx.StartTime = oneDialogue.StartTime
-	oneDialogueEx.EndTime = oneDialogue.EndTime
-	for _, line := range oneDialogue.Lines {
-		info := whatlanggo.DetectWithOptions(line, GetLangOptions())
-		tmpLang := -1
-		if IsWhiteListLang(info.Lang) == true {
-			tmpLang = (int)(info.Lang)
-		}
-		// 这一种语言的 key 是否存在,不存在则新建,存在再数值 +1
-		value, ok := langDict[tmpLang]
-		if ok == true {
-			// 累加
-			value++
-			langDict[tmpLang] = value
-		} else {
-			langDict[tmpLang] = 1
-		}
-		// 统计中文有多少行
-		if info.Lang == whatlanggo.Cmn {
-			*chLines = append(*chLines, line)
-		} else {
-			*otherLines = append(*otherLines, line)
-		}
-		// 这里可能是一个 dialogue 里面有两句话,而且两句话都是一个类型的语言,所以其实需要的是合并
-		switch info.Lang {
-		case whatlanggo.Cmn:
-			oneDialogueEx.ChLine += line + " "
-		case whatlanggo.Eng:
-			oneDialogueEx.EnLine += line + " "
-		case whatlanggo.Kor:
-			oneDialogueEx.KrLine += line + " "
-		case whatlanggo.Jpn:
-			oneDialogueEx.JpLine += line + " "
-		}
-	}
-
-	*usefulDialoguseEx = append(*usefulDialoguseEx, oneDialogueEx)
-}
-
-// SubLangStatistics2SubLangType 由分析的信息转换为具体是什么字幕的语言类型
-func SubLangStatistics2SubLangType(countLineFeed, AllLines float32, langDict map[int]int, chLines []string) types.Language {
-	const basePer = 0.8
-	// 是否是双语?
-	isDouble := false
-	perLines := countLineFeed / AllLines
-	// 第二行字幕出现的概率大于 80% 应该稳了吧,不然还能三语?
-	if perLines > basePer {
-		isDouble = true
-	}
-	// 中文(包含了 chs 以及 cht,这一级是无法区分的,需要额外的简体和繁体区分方法)
-	countChinese, hasChinese := langDict[int(whatlanggo.Cmn)]
-	// 英文
-	countEnglish, hasEnglish := langDict[int(whatlanggo.Eng)]
-	// 日文
-	countJapanese, hasJapanese := langDict[int(whatlanggo.Jpn)]
-	// 韩文
-	countKorean, hasKorean := langDict[int(whatlanggo.Kor)]
-	// 0 - No , 1 - Chs, 2 - Cht
-	isNoOrChsOrCht := 0
-	isChsCount := 0
-	if hasChinese {
-		for _, line := range chLines {
-			// 判断是简体还是繁体
-			if chDict.IsChs(line, 0.9) == true {
-				isChsCount++
-			}
-		}
-		// 简体句子的占比超过 80%
-		if float32(isChsCount)/float32(len(chLines)) > 0.8 {
-			isNoOrChsOrCht = 1
-		} else {
-			isNoOrChsOrCht = 2
-		}
-	}
-
-	// 这里有一种情况,就是双语的字幕不是在一个时间轴上的,而是分成两个时间轴的
-	// 那么之前的 isDouble 判断就失效了,需要补判一次
-	if isDouble == false {
-		if hasChinese && hasEnglish {
-			isDouble = isDoubleLang(countChinese, countEnglish)
-		}
-		if hasChinese && hasJapanese {
-			isDouble = isDoubleLang(countChinese, countJapanese)
-		}
-		if hasChinese && hasKorean {
-			isDouble = isDoubleLang(countChinese, countKorean)
-		}
-	}
-
-	// 优先判断双语
-	if isDouble == true {
-		// 首先得在外面统计就知道是双语
-		if hasChinese && hasEnglish {
-			// 简体	英文
-			return chIsChsOrCht(types.ChineseSimpleEnglish, isNoOrChsOrCht)
-		} else if hasChinese && hasJapanese {
-			// 简体 日文
-			return chIsChsOrCht(types.ChineseSimpleJapanese, isNoOrChsOrCht)
-		} else if hasChinese && hasKorean {
-			// 简体 韩文
-			return chIsChsOrCht(types.ChineseSimpleKorean, isNoOrChsOrCht)
-		} else if hasChinese {
-			return chIsChsOrCht(types.ChineseSimple, isNoOrChsOrCht)
-		} else if hasEnglish {
-			return types.English
-		} else if hasJapanese {
-			return types.Japanese
-		} else if hasKorean {
-			return types.Korean
-		} else {
-			return types.Unknow
-		}
-	} else {
-		// 如果比例达不到,那么就是单语言,所以最多的那个就是当前的语言
-		// 这里的字典是有可能出现
-		if hasChinese {
-			// 那么起码要占比 80% 对吧
-			perLines = float32(countChinese) / AllLines
-			if perLines > basePer {
-				return chIsChsOrCht(types.ChineseSimple, isNoOrChsOrCht)
-			}
-		}
-		if hasEnglish {
-			// 那么起码要占比 80% 对吧
-			perLines = float32(countEnglish) / AllLines
-			if perLines > basePer {
-				return types.English
-			}
-		}
-		if hasJapanese {
-			// 那么起码要占比 80% 对吧
-			perLines = float32(countJapanese) / AllLines
-			if perLines > basePer {
-				return types.Japanese
-			}
-		}
-		if hasKorean {
-			// 那么起码要占比 80% 对吧
-			perLines = float32(countKorean) / AllLines
-			if perLines > basePer {
-				return types.Korean
-			}
-		}
-
-		return types.Unknow
-	}
-
-}
-
-// 跟中文相关的再使用,其他的无需传入
-func chIsChsOrCht(language types.Language, isNoOrChsOrCht int) types.Language {
-	// 输出原来的
-	if isNoOrChsOrCht == 0 || isNoOrChsOrCht == 1 {
-		return language
-	}
-	switch language {
-	case types.ChineseSimpleEnglish:
-		// 简体	英文
-		return types.ChineseTraditionalEnglish
-	case types.ChineseSimpleJapanese:
-		// 简体 日文
-		return types.ChineseTraditionalJapanese
-	case types.ChineseSimpleKorean:
-		// 简体 韩文
-		return types.ChineseTraditionalKorean
-	case types.ChineseSimple:
-		// 简体
-		return types.ChineseTraditional
-	default:
-		return language
-	}
-}
-
-// IsChineseSimpleOrTraditional 暂时弃用,在 SubLangStatistics2SubLangType 检测语言,通过 unicode 做到。 从字幕的文件名称中尝试确认是简体还是繁体,不需要判断双语问题,有额外的解析器完成。只可能出现 ChineseSimple ChineseTraditional Unknow 三种情况
-func IsChineseSimpleOrTraditional(inputFileName string, orgLang types.Language) types.Language {
-	if strings.Contains(inputFileName, types.SubNameKeywordChineseSimple) || strings.Contains(inputFileName, types.MatchLangChs) {
-		// 简体中文关键词的匹配
-		return orgLang
-	} else if strings.Contains(inputFileName, types.SubNameKeywordTraditional) || strings.Contains(inputFileName, types.MatchLangCht) {
-		// 繁体中文关键词的匹配
-		if orgLang == types.ChineseSimple {
-			// 简体 -> 繁体
-			return types.ChineseTraditional
-		} else if orgLang == types.ChineseSimpleEnglish {
-			// 简体英文 -> 繁体英文
-			return types.ChineseTraditionalEnglish
-		} else if orgLang == types.ChineseSimpleJapanese {
-			// 简体日文 -> 繁体日文
-			return types.ChineseTraditionalJapanese
-		} else if orgLang == types.ChineseSimpleKorean {
-			// 简体韩文 -> 繁体韩文
-			return types.ChineseTraditionalKorean
-		}
-		// 进来了都不是,那么就返回原来的语言
-		return orgLang
-	} else {
-		// 都没有匹配上,返回原来识别出来的类型即可
-		return orgLang
-	}
-}
-
-// ConvertToString 将字符串从原始编码转换到目标编码,需要配合字符串检测编码库使用 chardet.NewTextDetector()
-func ConvertToString(src string, srcCode string, tagCode string) string {
-	defer func() {
-		if err := recover(); err != nil {
-			log_helper.GetLogger().Errorln("ConvertToString panic:", err)
-		}
-	}()
-	srcCoder := mahonia.NewDecoder(srcCode)
-	srcResult := srcCoder.ConvertString(src)
-	tagCoder := mahonia.NewDecoder(tagCode)
-	_, cdata, _ := tagCoder.Translate([]byte(srcResult), true)
-	result := string(cdata)
-	return result
-}
-
-// 感谢: https://blog.csdn.net/gaoluhua/article/details/109128154,解决了编码问题
-
-// ChangeFileCoding2UTF8 自动检测文件的编码,然后转换到 UTF-8
-func ChangeFileCoding2UTF8(inBytes []byte) ([]byte, error) {
-	best, err := detector.DetectBest(inBytes)
-	utf8String := ""
-	if err != nil {
-		return nil, err
-	}
-	if best.Confidence < 90 {
-		detectBest := nzlov.Mostlike(inBytes)
-		utf8String, err = charset.ToUTF8(charset.Charset(detectBest), string(inBytes))
-	} else {
-		utf8String, err = charset.ToUTF8(charset.Charset(best.Charset), string(inBytes))
-	}
-	if err != nil {
-		return nil, err
-	}
-	if utf8String == "" {
-		return inBytes, nil
-	}
-	return []byte(utf8String), nil
-}
-
-func isDoubleLang(count0, count1 int) bool {
-	if count0 >= count1 {
-		f := float32(count0) / float32(count1)
-		if f >= 1 && f <= 1.4 {
-			return true
-		} else {
-			return false
-		}
-	} else {
-		f := float32(count1) / float32(count0)
-		if f >= 1 && f <= 1.4 {
-			return true
-		} else {
-			return false
-		}
-	}
-}
-
-var (
-	chDict   = sat.DefaultDict()
-	detector = chardet.NewTextDetector()
-)

+ 185 - 0
internal/pkg/language/my_language.go

@@ -0,0 +1,185 @@
+package language
+
+import (
+	"github.com/allanpk716/ChineseSubFinder/internal/types/language"
+	"strings"
+)
+
+// LangConverter4Sub_Supplier 语言转换器,给字幕的提供者实例解析使用(xunlei、zimuku等)
+// 支持的字符串语言见 internal/types/language/my_language.go
+func LangConverter4Sub_Supplier(subLang string) language.MyLanguage {
+	/*
+		xunlei:未知语言、简体&英语、繁体&英语、简体、繁体、英语
+	*/
+	if strings.Contains(subLang, language.MatchLangDouble) {
+		// 双语 - 简英
+		return language.ChineseSimpleEnglish
+	} else if strings.Contains(subLang, language.MatchLangChs) {
+		// 优先简体
+		if strings.Contains(subLang, language.MatchLangEn) {
+			// 简英
+			return language.ChineseSimpleEnglish
+		} else if strings.Contains(subLang, language.MatchLangJp) {
+			// 简日
+			return language.ChineseSimpleJapanese
+		} else if strings.Contains(subLang, language.MatchLangKr) {
+			// 简韩
+			return language.ChineseSimpleKorean
+		}
+		// 默认简体中文
+		return language.ChineseSimple
+	} else if strings.Contains(subLang, language.MatchLangCht) {
+		// 然后是繁体
+		if strings.Contains(subLang, language.MatchLangEn) {
+			// 繁英
+			return language.ChineseTraditionalEnglish
+		} else if strings.Contains(subLang, language.MatchLangJp) {
+			// 繁日
+			return language.ChineseTraditionalJapanese
+		} else if strings.Contains(subLang, language.MatchLangKr) {
+			// 繁韩
+			return language.ChineseTraditionalKorean
+		}
+		// 默认繁体中文
+		return language.ChineseTraditional
+	} else if strings.Contains(subLang, language.MatchLangEn) {
+		// 英文
+		return language.English
+	} else if strings.Contains(subLang, language.MatchLangJp) {
+		// 日文
+		return language.Japanese
+	} else if strings.Contains(subLang, language.MatchLangKr) {
+		// 韩文
+		return language.Korean
+	} else {
+		// 都没有,则标记未知
+		return language.Unknown
+	}
+}
+
+// HasChineseLang 是否包含中文
+func HasChineseLang(lan language.MyLanguage) bool {
+	switch lan {
+	case language.ChineseSimple,
+		language.ChineseTraditional,
+
+		language.ChineseSimpleEnglish,
+		language.ChineseTraditionalEnglish,
+
+		language.ChineseSimpleJapanese,
+		language.ChineseTraditionalJapanese,
+
+		language.ChineseSimpleKorean,
+		language.ChineseTraditionalKorean:
+		return true
+	default:
+		return false
+	}
+}
+
+// IsBilingualSubtitle 是否是双语字幕
+func IsBilingualSubtitle(lan language.MyLanguage) bool {
+	switch lan {
+	case language.ChineseSimpleEnglish,
+		language.ChineseTraditionalEnglish,
+
+		language.ChineseSimpleJapanese,
+		language.ChineseTraditionalJapanese,
+
+		language.ChineseSimpleKorean,
+		language.ChineseTraditionalKorean:
+		return true
+	default:
+		return false
+	}
+}
+
+// Lang2ChineseString 将 types.MyLanguage 转换为中文描述:简、繁、简英
+// 支持的字符串语言见 internal/types/language/my_language.go
+func Lang2ChineseString(lan language.MyLanguage) string {
+	switch lan {
+	case language.Unknown:
+		// 未知语言
+		return language.MathLangChnUnknown
+	case language.ChineseSimple:
+		// 简体中文
+		return language.MatchLangChs
+	case language.ChineseTraditional:
+		// 繁体中文
+		return language.MatchLangCht
+	case language.ChineseSimpleEnglish:
+		// 简英双语字幕
+		return language.MatchLangChsEn
+	case language.ChineseTraditionalEnglish:
+		// 繁英双语字幕
+		return language.MatchLangChtEn
+	case language.English:
+		// 英文
+		return language.MatchLangEn
+	case language.Japanese:
+		// 日语
+		return language.MatchLangJp
+	case language.ChineseSimpleJapanese:
+		// 简日双语字幕
+		return language.MatchLangChsJp
+	case language.ChineseTraditionalJapanese:
+		// 繁日双语字幕
+		return language.MatchLangChtJp
+	case language.Korean:
+		// 韩语
+		return language.MatchLangKr
+	case language.ChineseSimpleKorean:
+		// 简韩双语字幕
+		return language.MatchLangChsKr
+	case language.ChineseTraditionalKorean:
+		// 繁韩双语字幕
+		return language.MatchLangChtKr
+	default:
+		return language.MathLangChnUnknown
+	}
+}
+
+// ChineseString2Lang 将 中文描述:简、繁、简英 转换为 types.MyLanguage
+// 支持的字符串语言见 internal/types/language/my_language.go
+func ChineseString2Lang(chineseStr string) language.MyLanguage {
+	switch chineseStr {
+	case language.MathLangChnUnknown:
+		// 未知语言
+		return language.Unknown
+	case language.MatchLangChs:
+		// 简体中文
+		return language.ChineseSimple
+	case language.MatchLangCht:
+		// 繁体中文
+		return language.ChineseTraditional
+	case language.MatchLangChsEn:
+		// 简英双语字幕
+		return language.ChineseSimpleEnglish
+	case language.MatchLangChtEn:
+		// 繁英双语字幕
+		return language.ChineseTraditionalEnglish
+	case language.MatchLangEn:
+		// 英文
+		return language.English
+	case language.MatchLangJp:
+		// 日语
+		return language.Japanese
+	case language.MatchLangChsJp:
+		// 简日双语字幕
+		return language.ChineseSimpleJapanese
+	case language.MatchLangChtJp:
+		// 繁日双语字幕
+		return language.ChineseTraditionalJapanese
+	case language.MatchLangKr:
+		// 韩语
+		return language.Korean
+	case language.MatchLangChsKr:
+		// 简韩双语字幕
+		return language.ChineseSimpleKorean
+	case language.MatchLangChtKr:
+		// 繁韩双语字幕
+		return language.ChineseTraditionalKorean
+	default:
+		return language.Unknown
+	}
+}

+ 47 - 0
internal/pkg/language/string_encoding.go

@@ -0,0 +1,47 @@
+package language
+
+import (
+	"github.com/allanpk716/ChineseSubFinder/internal/logic/charset"
+	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
+	"github.com/axgle/mahonia"
+	nzlov "github.com/nzlov/chardet"
+)
+
+// ConvertToString 将字符串从原始编码转换到目标编码,需要配合字符串检测编码库使用 chardet.NewTextDetector()
+func ConvertToString(src string, srcCode string, tagCode string) string {
+	defer func() {
+		if err := recover(); err != nil {
+			log_helper.GetLogger().Errorln("ConvertToString panic:", err)
+		}
+	}()
+	srcCoder := mahonia.NewDecoder(srcCode)
+	srcResult := srcCoder.ConvertString(src)
+	tagCoder := mahonia.NewDecoder(tagCode)
+	_, cdata, _ := tagCoder.Translate([]byte(srcResult), true)
+	result := string(cdata)
+	return result
+}
+
+// 感谢: https://blog.csdn.net/gaoluhua/article/details/109128154,解决了编码问题
+
+// ChangeFileCoding2UTF8 自动检测文件的编码,然后转换到 UTF-8
+func ChangeFileCoding2UTF8(inBytes []byte) ([]byte, error) {
+	best, err := detector.DetectBest(inBytes)
+	utf8String := ""
+	if err != nil {
+		return nil, err
+	}
+	if best.Confidence < 90 {
+		detectBest := nzlov.Mostlike(inBytes)
+		utf8String, err = charset.ToUTF8(charset.Charset(detectBest), string(inBytes))
+	} else {
+		utf8String, err = charset.ToUTF8(charset.Charset(best.Charset), string(inBytes))
+	}
+	if err != nil {
+		return nil, err
+	}
+	if utf8String == "" {
+		return inBytes, nil
+	}
+	return []byte(utf8String), nil
+}

+ 225 - 0
internal/pkg/language/whatlanggo.go

@@ -0,0 +1,225 @@
+package language
+
+import (
+	"github.com/abadojack/whatlanggo"
+	"github.com/allanpk716/ChineseSubFinder/internal/types/language"
+	"github.com/allanpk716/ChineseSubFinder/internal/types/subparser"
+)
+
+// GetLangOptions 语言识别的 Options Whitelist
+func GetLangOptions() whatlanggo.Options {
+	return whatlanggo.Options{
+		Whitelist: map[whatlanggo.Lang]bool{
+			whatlanggo.Cmn: true, // 中文	11
+			whatlanggo.Eng: true, // 英文	15
+			whatlanggo.Jpn: true, // 日文	32
+			whatlanggo.Kor: true, // 韩文	37
+		},
+	}
+}
+
+// IsWhiteListLang 是否是白名单语言
+func IsWhiteListLang(lang whatlanggo.Lang) bool {
+	switch lang {
+	// 中文 英文 日文 韩文
+	case whatlanggo.Cmn, whatlanggo.Eng, whatlanggo.Jpn, whatlanggo.Kor:
+		return true
+	default:
+		return false
+	}
+}
+
+// DetectSubLangAndStatistics 检测语言然后统计
+func DetectSubLangAndStatistics(oneDialogue subparser.OneDialogue, langDict map[int]int, usefulDialoguseEx *[]subparser.OneDialogueEx, chLines *[]string, otherLines *[]string) {
+
+	var oneDialogueEx subparser.OneDialogueEx
+	oneDialogueEx.StartTime = oneDialogue.StartTime
+	oneDialogueEx.EndTime = oneDialogue.EndTime
+	for _, line := range oneDialogue.Lines {
+		info := whatlanggo.DetectWithOptions(line, GetLangOptions())
+		tmpLang := -1
+		if IsWhiteListLang(info.Lang) == true {
+			tmpLang = (int)(info.Lang)
+		}
+		// 这一种语言的 key 是否存在,不存在则新建,存在再数值 +1
+		value, ok := langDict[tmpLang]
+		if ok == true {
+			// 累加
+			value++
+			langDict[tmpLang] = value
+		} else {
+			langDict[tmpLang] = 1
+		}
+		// 统计中文有多少行
+		if info.Lang == whatlanggo.Cmn {
+			*chLines = append(*chLines, line)
+		} else {
+			*otherLines = append(*otherLines, line)
+		}
+		// 这里可能是一个 dialogue 里面有两句话,而且两句话都是一个类型的语言,所以其实需要的是合并
+		switch info.Lang {
+		case whatlanggo.Cmn:
+			oneDialogueEx.ChLine += line + " "
+		case whatlanggo.Eng:
+			oneDialogueEx.EnLine += line + " "
+		case whatlanggo.Kor:
+			oneDialogueEx.KrLine += line + " "
+		case whatlanggo.Jpn:
+			oneDialogueEx.JpLine += line + " "
+		}
+	}
+
+	*usefulDialoguseEx = append(*usefulDialoguseEx, oneDialogueEx)
+}
+
+// SubLangStatistics2SubLangType 由分析的信息转换为具体是什么字幕的语言类型
+func SubLangStatistics2SubLangType(countLineFeed, AllLines float32, langDict map[int]int, chLines []string) language.MyLanguage {
+	const basePer = 0.8
+	// 是否是双语?
+	isDouble := false
+	perLines := countLineFeed / AllLines
+	// 第二行字幕出现的概率大于 80% 应该稳了吧,不然还能三语?
+	if perLines > basePer {
+		isDouble = true
+	}
+	// 中文(包含了 chs 以及 cht,这一级是无法区分的,需要额外的简体和繁体区分方法)
+	countChinese, hasChinese := langDict[int(whatlanggo.Cmn)]
+	// 英文
+	countEnglish, hasEnglish := langDict[int(whatlanggo.Eng)]
+	// 日文
+	countJapanese, hasJapanese := langDict[int(whatlanggo.Jpn)]
+	// 韩文
+	countKorean, hasKorean := langDict[int(whatlanggo.Kor)]
+	// 0 - No , 1 - Chs, 2 - Cht
+	isNoOrChsOrCht := 0
+	isChsCount := 0
+	if hasChinese {
+		for _, line := range chLines {
+			// 判断是简体还是繁体
+			if chDict.IsChs(line, 0.9) == true {
+				isChsCount++
+			}
+		}
+		// 简体句子的占比超过 80%
+		if float32(isChsCount)/float32(len(chLines)) > 0.8 {
+			isNoOrChsOrCht = 1
+		} else {
+			isNoOrChsOrCht = 2
+		}
+	}
+
+	// 这里有一种情况,就是双语的字幕不是在一个时间轴上的,而是分成两个时间轴的
+	// 那么之前的 isDouble 判断就失效了,需要补判一次
+	if isDouble == false {
+		if hasChinese && hasEnglish {
+			isDouble = isDoubleLang(countChinese, countEnglish)
+		}
+		if hasChinese && hasJapanese {
+			isDouble = isDoubleLang(countChinese, countJapanese)
+		}
+		if hasChinese && hasKorean {
+			isDouble = isDoubleLang(countChinese, countKorean)
+		}
+	}
+
+	// 优先判断双语
+	if isDouble == true {
+		// 首先得在外面统计就知道是双语
+		if hasChinese && hasEnglish {
+			// 简体	英文
+			return chIsChsOrCht(language.ChineseSimpleEnglish, isNoOrChsOrCht)
+		} else if hasChinese && hasJapanese {
+			// 简体 日文
+			return chIsChsOrCht(language.ChineseSimpleJapanese, isNoOrChsOrCht)
+		} else if hasChinese && hasKorean {
+			// 简体 韩文
+			return chIsChsOrCht(language.ChineseSimpleKorean, isNoOrChsOrCht)
+		} else if hasChinese {
+			return chIsChsOrCht(language.ChineseSimple, isNoOrChsOrCht)
+		} else if hasEnglish {
+			return language.English
+		} else if hasJapanese {
+			return language.Japanese
+		} else if hasKorean {
+			return language.Korean
+		} else {
+			return language.Unknown
+		}
+	} else {
+		// 如果比例达不到,那么就是单语言,所以最多的那个就是当前的语言
+		// 这里的字典是有可能出现
+		if hasChinese {
+			// 那么起码要占比 80% 对吧
+			perLines = float32(countChinese) / AllLines
+			if perLines > basePer {
+				return chIsChsOrCht(language.ChineseSimple, isNoOrChsOrCht)
+			}
+		}
+		if hasEnglish {
+			// 那么起码要占比 80% 对吧
+			perLines = float32(countEnglish) / AllLines
+			if perLines > basePer {
+				return language.English
+			}
+		}
+		if hasJapanese {
+			// 那么起码要占比 80% 对吧
+			perLines = float32(countJapanese) / AllLines
+			if perLines > basePer {
+				return language.Japanese
+			}
+		}
+		if hasKorean {
+			// 那么起码要占比 80% 对吧
+			perLines = float32(countKorean) / AllLines
+			if perLines > basePer {
+				return language.Korean
+			}
+		}
+
+		return language.Unknown
+	}
+
+}
+
+// 跟中文相关的再使用,其他的无需传入
+func chIsChsOrCht(inLanguage language.MyLanguage, isNoOrChsOrCht int) language.MyLanguage {
+	// 输出原来的
+	if isNoOrChsOrCht == 0 || isNoOrChsOrCht == 1 {
+		return inLanguage
+	}
+	switch inLanguage {
+	case language.ChineseSimpleEnglish:
+		// 简体	英文
+		return language.ChineseTraditionalEnglish
+	case language.ChineseSimpleJapanese:
+		// 简体 日文
+		return language.ChineseTraditionalJapanese
+	case language.ChineseSimpleKorean:
+		// 简体 韩文
+		return language.ChineseTraditionalKorean
+	case language.ChineseSimple:
+		// 简体
+		return language.ChineseTraditional
+	default:
+		return inLanguage
+	}
+}
+
+func isDoubleLang(count0, count1 int) bool {
+	if count0 >= count1 {
+		f := float32(count0) / float32(count1)
+		if f >= 1 && f <= 1.4 {
+			return true
+		} else {
+			return false
+		}
+	} else {
+		f := float32(count1) / float32(count0)
+		if f >= 1 && f <= 1.4 {
+			return true
+		} else {
+			return false
+		}
+	}
+}

+ 13 - 13
internal/pkg/sub_formatter/emby/emby.go

@@ -3,7 +3,7 @@ package emby
 import (
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/language"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_formatter/common"
-	"github.com/allanpk716/ChineseSubFinder/internal/types"
+	language2 "github.com/allanpk716/ChineseSubFinder/internal/types/language"
 	"path/filepath"
 	"regexp"
 	"strings"
@@ -25,8 +25,8 @@ func (f Formatter) GetFormatterFormatterName() int {
 	return int(common.Emby)
 }
 
-// IsMatchThisFormat 是否满足当前实现接口的字幕命名格式 - 是否符合规则、fileNameWithOutExt string, subExt string, subLang types.Language, extraSubPreName string
-func (f Formatter) IsMatchThisFormat(subName string) (bool, string, string, types.Language, string) {
+// IsMatchThisFormat 是否满足当前实现接口的字幕命名格式 - 是否符合规则、fileNameWithOutExt string, subExt string, subLang types.MyLanguage, extraSubPreName string
+func (f Formatter) IsMatchThisFormat(subName string) (bool, string, string, language2.MyLanguage, string) {
 	/*
 		Emby 的命名规则比较特殊,而且本程序就是做中文字幕下载的,所以,下面的正则表达式比较特殊
 	*/
@@ -38,9 +38,9 @@ func (f Formatter) IsMatchThisFormat(subName string) (bool, string, string, type
 		[0][2]	.ass
 	*/
 	if matched == nil || len(matched) < 1 || len(matched[0]) < 3 {
-		return false, "", "", types.Unknow, ""
+		return false, "", "", language2.Unknown, ""
 	}
-	var subLang types.Language
+	var subLang language2.MyLanguage
 	var subLangStr string
 	var extraSubPreName string
 	fileNameWithOutExt := strings.ReplaceAll(subName, matched[0][0], "")
@@ -49,7 +49,7 @@ func (f Formatter) IsMatchThisFormat(subName string) (bool, string, string, type
 	if strings.Contains(midString, ",") == true {
 		tmps := strings.Split(midString, ",")
 		if len(tmps) < 2 {
-			return false, "", "", types.Unknow, ""
+			return false, "", "", language2.Unknown, ""
 		}
 		subLangStr = tmps[0]
 		extraSubPreName = tmps[1]
@@ -63,7 +63,7 @@ func (f Formatter) IsMatchThisFormat(subName string) (bool, string, string, type
 }
 
 // GenerateMixSubName 通过视频和字幕信息,生成当前实现接口的字幕命名格式。extraSubPreName 一般是填写字幕网站,不填写则留空 - 新名称、新名称带有 default 标记,新名称带有 forced 标记
-func (f Formatter) GenerateMixSubName(videoFileName, subExt string, subLang types.Language, extraSubPreName string) (string, string, string) {
+func (f Formatter) GenerateMixSubName(videoFileName, subExt string, subLang language2.MyLanguage, extraSubPreName string) (string, string, string) {
 	/*
 		这里会生成类似的文件名 xxxx.chinese(中英,shooter)
 	*/
@@ -72,19 +72,19 @@ func (f Formatter) GenerateMixSubName(videoFileName, subExt string, subLang type
 	return f.GenerateMixSubNameBase(videoFileNameWithOutExt, subExt, subLang, extraSubPreName)
 }
 
-func (f Formatter) GenerateMixSubNameBase(fileNameWithOutExt, subExt string, subLang types.Language, extraSubPreName string) (string, string, string) {
+func (f Formatter) GenerateMixSubNameBase(fileNameWithOutExt, subExt string, subLang language2.MyLanguage, extraSubPreName string) (string, string, string) {
 	// 这里传入字幕后缀名的时候,可能会带有 default 或者 forced 字段,需要剔除
-	nowSubExt := strings.ReplaceAll(subExt, types.Sub_Ext_Mark_Default, "")
-	nowSubExt = strings.ReplaceAll(subExt, types.Sub_Ext_Mark_Forced, "")
+	nowSubExt := strings.ReplaceAll(subExt, language2.Sub_Ext_Mark_Default, "")
+	nowSubExt = strings.ReplaceAll(subExt, language2.Sub_Ext_Mark_Forced, "")
 	note := ""
 	// extraSubPreName 那个字幕网站下载的
 	if extraSubPreName != "" {
 		note = "," + extraSubPreName
 	}
 
-	subNewName := fileNameWithOutExt + types.Emby_chinese + "(" + language.Lang2ChineseString(subLang) + note + ")" + nowSubExt
-	subNewNameWithDefault := fileNameWithOutExt + types.Emby_chinese + "(" + language.Lang2ChineseString(subLang) + note + ")" + types.Sub_Ext_Mark_Default + nowSubExt
-	subNewNameWithForced := fileNameWithOutExt + types.Emby_chinese + "(" + language.Lang2ChineseString(subLang) + note + ")" + types.Sub_Ext_Mark_Forced + nowSubExt
+	subNewName := fileNameWithOutExt + language2.Emby_chinese + "(" + language.Lang2ChineseString(subLang) + note + ")" + nowSubExt
+	subNewNameWithDefault := fileNameWithOutExt + language2.Emby_chinese + "(" + language.Lang2ChineseString(subLang) + note + ")" + language2.Sub_Ext_Mark_Default + nowSubExt
+	subNewNameWithForced := fileNameWithOutExt + language2.Emby_chinese + "(" + language.Lang2ChineseString(subLang) + note + ")" + language2.Sub_Ext_Mark_Forced + nowSubExt
 
 	return subNewName, subNewNameWithDefault, subNewNameWithForced
 }

+ 13 - 13
internal/pkg/sub_formatter/emby/emby_test.go

@@ -3,7 +3,7 @@ package emby
 import (
 	"github.com/allanpk716/ChineseSubFinder/internal/common"
 	subCommon "github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_formatter/common"
-	"github.com/allanpk716/ChineseSubFinder/internal/types"
+	"github.com/allanpk716/ChineseSubFinder/internal/types/language"
 	"testing"
 )
 
@@ -27,50 +27,50 @@ func TestFormatter_IsMatchThisFormat(t *testing.T) {
 		want  bool
 		want1 string
 		want2 string
-		want3 types.Language
+		want3 language.MyLanguage
 		want4 string
 	}{
 		{name: "00", args: args{subName: "The Boss Baby Family Business (2021) WEBDL-1080p.chinese(简英,subhd).ass"},
 			want:  true,
 			want1: fileWithOutExt,
 			want2: ".ass",
-			want3: types.ChineseSimpleEnglish,
+			want3: language.ChineseSimpleEnglish,
 			want4: "subhd"},
 		{name: "01", args: args{subName: "The Boss Baby Family Business (2021) WEBDL-1080p.chinese(简英,xunlei).default.ass"},
 			want:  true,
 			want1: fileWithOutExt,
 			want2: ".default.ass",
-			want3: types.ChineseSimpleEnglish,
+			want3: language.ChineseSimpleEnglish,
 			want4: "xunlei"},
 		{name: "02", args: args{subName: "The Boss Baby Family Business (2021) WEBDL-1080p.chinese(简英,zimuku).forced.ass"},
 			want:  true,
 			want1: fileWithOutExt,
 			want2: ".forced.ass",
-			want3: types.ChineseSimpleEnglish,
+			want3: language.ChineseSimpleEnglish,
 			want4: "zimuku"},
 		{name: "10", args: args{subName: "The Boss Baby Family Business (2021) WEBDL-1080p.chinese(简日).ass"},
 			want:  true,
 			want1: fileWithOutExt,
 			want2: ".ass",
-			want3: types.ChineseSimpleJapanese,
+			want3: language.ChineseSimpleJapanese,
 			want4: ""},
 		{name: "11", args: args{subName: "The Boss Baby Family Business (2021) WEBDL-1080p.chinese(简).default.ass"},
 			want:  true,
 			want1: fileWithOutExt,
 			want2: ".default.ass",
-			want3: types.ChineseSimple,
+			want3: language.ChineseSimple,
 			want4: ""},
 		{name: "12", args: args{subName: "The Boss Baby Family Business (2021) WEBDL-1080p.chinese(繁英).forced.ass"},
 			want:  true,
 			want1: fileWithOutExt,
 			want2: ".forced.ass",
-			want3: types.ChineseTraditionalEnglish,
+			want3: language.ChineseTraditionalEnglish,
 			want4: ""},
 		{name: "03", args: args{subName: "The Boss Baby Family Business (2021) WEBDL-1080p.chinese.ass"},
 			want:  false,
 			want1: "",
 			want2: "",
-			want3: types.Unknow,
+			want3: language.Unknown,
 			want4: ""},
 	}
 	for _, tt := range tests {
@@ -104,7 +104,7 @@ func TestFormatter_GenerateMixSubName(t *testing.T) {
 	type args struct {
 		videoFileName   string
 		subExt          string
-		subLang         types.Language
+		subLang         language.MyLanguage
 		extraSubPreName string
 	}
 	tests := []struct {
@@ -114,15 +114,15 @@ func TestFormatter_GenerateMixSubName(t *testing.T) {
 		want1 string
 		want2 string
 	}{
-		{name: "zh_shooter", args: args{videoFileName: videoFileName, subExt: common.SubExtASS, subLang: types.ChineseSimple, extraSubPreName: "shooter"},
+		{name: "zh_shooter", args: args{videoFileName: videoFileName, subExt: common.SubExtASS, subLang: language.ChineseSimple, extraSubPreName: "shooter"},
 			want:  videoFileNamePre + ".chinese(简,shooter).ass",
 			want1: videoFileNamePre + ".chinese(简,shooter).default.ass",
 			want2: videoFileNamePre + ".chinese(简,shooter).forced.ass"},
-		{name: "zh_en_shooter", args: args{videoFileName: videoFileName, subExt: common.SubExtASS, subLang: types.ChineseSimpleEnglish, extraSubPreName: "shooter"},
+		{name: "zh_en_shooter", args: args{videoFileName: videoFileName, subExt: common.SubExtASS, subLang: language.ChineseSimpleEnglish, extraSubPreName: "shooter"},
 			want:  videoFileNamePre + ".chinese(简英,shooter).ass",
 			want1: videoFileNamePre + ".chinese(简英,shooter).default.ass",
 			want2: videoFileNamePre + ".chinese(简英,shooter).forced.ass"},
-		{name: "zh_en", args: args{videoFileName: videoFileName, subExt: common.SubExtASS, subLang: types.ChineseSimpleEnglish, extraSubPreName: ""},
+		{name: "zh_en", args: args{videoFileName: videoFileName, subExt: common.SubExtASS, subLang: language.ChineseSimpleEnglish, extraSubPreName: ""},
 			want:  videoFileNamePre + ".chinese(简英).ass",
 			want1: videoFileNamePre + ".chinese(简英).default.ass",
 			want2: videoFileNamePre + ".chinese(简英).forced.ass"},

+ 12 - 12
internal/pkg/sub_formatter/normal/normal.go

@@ -5,7 +5,7 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/logic/sub_parser/srt"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_formatter/common"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_parser_hub"
-	"github.com/allanpk716/ChineseSubFinder/internal/types"
+	"github.com/allanpk716/ChineseSubFinder/internal/types/language"
 	"path/filepath"
 	"regexp"
 	"strings"
@@ -28,8 +28,8 @@ func (f Formatter) GetFormatterFormatterName() int {
 	return int(common.Normal)
 }
 
-// IsMatchThisFormat 是否满足当前实现接口的字幕命名格式 - 是否符合规则、fileNameWithOutExt string, subExt string, subLang types.Language, extraSubPreName string
-func (f Formatter) IsMatchThisFormat(subName string) (bool, string, string, types.Language, string) {
+// IsMatchThisFormat 是否满足当前实现接口的字幕命名格式 - 是否符合规则、fileNameWithOutExt string, subExt string, subLang types.MyLanguage, extraSubPreName string
+func (f Formatter) IsMatchThisFormat(subName string) (bool, string, string, language.MyLanguage, string) {
 	/*
 		Emby 的命名规则比较特殊,而且本程序就是做中文字幕下载的,所以,下面的正则表达式比较特殊
 	*/
@@ -51,9 +51,9 @@ func (f Formatter) IsMatchThisFormat(subName string) (bool, string, string, type
 		[0][2]	.ass
 	*/
 	if matched == nil || len(matched) < 1 || len(matched[0]) < 3 {
-		return false, "", "", types.Unknow, ""
+		return false, "", "", language.Unknown, ""
 	}
-	var subLang types.Language
+	var subLang language.MyLanguage
 	var extraSubPreName string
 	fileNameWithOutExt := strings.ReplaceAll(subName, matched[0][0], "")
 	subExt := matched[0][2]
@@ -71,7 +71,7 @@ func (f Formatter) IsMatchThisFormat(subName string) (bool, string, string, type
 }
 
 // GenerateMixSubName 通过视频和字幕信息,生成当前实现接口的字幕命名格式。extraSubPreName 一般是填写字幕网站,不填写则留空 - 新名称、新名称带有 default 标记,新名称带有 forced 标记
-func (f Formatter) GenerateMixSubName(videoFileName, subExt string, subLang types.Language, extraSubPreName string) (string, string, string) {
+func (f Formatter) GenerateMixSubName(videoFileName, subExt string, subLang language.MyLanguage, extraSubPreName string) (string, string, string) {
 	/*
 		这里会生成类似的文件名 xxxx.zh
 	*/
@@ -80,14 +80,14 @@ func (f Formatter) GenerateMixSubName(videoFileName, subExt string, subLang type
 	return f.GenerateMixSubNameBase(videoFileNameWithOutExt, subExt, subLang, extraSubPreName)
 }
 
-func (f Formatter) GenerateMixSubNameBase(fileNameWithOutExt, subExt string, subLang types.Language, extraSubPreName string) (string, string, string) {
+func (f Formatter) GenerateMixSubNameBase(fileNameWithOutExt, subExt string, subLang language.MyLanguage, extraSubPreName string) (string, string, string) {
 	// 这里传入字幕后缀名的时候,可能会带有 default 或者 forced 字段,需要剔除
-	nowSubExt := strings.ReplaceAll(subExt, types.Sub_Ext_Mark_Default, "")
-	nowSubExt = strings.ReplaceAll(subExt, types.Sub_Ext_Mark_Forced, "")
+	nowSubExt := strings.ReplaceAll(subExt, language.Sub_Ext_Mark_Default, "")
+	nowSubExt = strings.ReplaceAll(subExt, language.Sub_Ext_Mark_Forced, "")
 
-	subNewName := fileNameWithOutExt + "." + types.ChineseAbbr_639_1 + nowSubExt
-	subNewNameWithDefault := fileNameWithOutExt + "." + types.ChineseAbbr_639_1 + types.Sub_Ext_Mark_Default + nowSubExt
-	subNewNameWithForced := fileNameWithOutExt + "." + types.ChineseAbbr_639_1 + types.Sub_Ext_Mark_Forced + nowSubExt
+	subNewName := fileNameWithOutExt + "." + language.ISO_639_1_Chinese + nowSubExt
+	subNewNameWithDefault := fileNameWithOutExt + "." + language.ISO_639_1_Chinese + language.Sub_Ext_Mark_Default + nowSubExt
+	subNewNameWithForced := fileNameWithOutExt + "." + language.ISO_639_1_Chinese + language.Sub_Ext_Mark_Forced + nowSubExt
 
 	return subNewName, subNewNameWithDefault, subNewNameWithForced
 }

+ 10 - 10
internal/pkg/sub_formatter/normal/normal_test.go

@@ -3,7 +3,7 @@ package normal
 import (
 	"github.com/allanpk716/ChineseSubFinder/internal/common"
 	subCommon "github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_formatter/common"
-	"github.com/allanpk716/ChineseSubFinder/internal/types"
+	"github.com/allanpk716/ChineseSubFinder/internal/types/language"
 	"testing"
 )
 
@@ -27,32 +27,32 @@ func TestFormatter_IsMatchThisFormat(t *testing.T) {
 		want  bool
 		want1 string
 		want2 string
-		want3 types.Language
+		want3 language.MyLanguage
 		want4 string
 	}{
 		{name: "00", args: args{subName: "The Boss Baby Family Business (2021) WEBDL-1080p.zh.ass"},
 			want:  true,
 			want1: fileWithOutExt,
 			want2: ".ass",
-			want3: types.ChineseSimple,
+			want3: language.ChineseSimple,
 			want4: ""},
 		{name: "01", args: args{subName: "The Boss Baby Family Business (2021) WEBDL-1080p.zh.default.ass"},
 			want:  true,
 			want1: fileWithOutExt,
 			want2: ".default.ass",
-			want3: types.ChineseSimple,
+			want3: language.ChineseSimple,
 			want4: ""},
 		{name: "02", args: args{subName: "The Boss Baby Family Business (2021) WEBDL-1080p.zh.forced.ass"},
 			want:  true,
 			want1: fileWithOutExt,
 			want2: ".forced.ass",
-			want3: types.ChineseSimple,
+			want3: language.ChineseSimple,
 			want4: ""},
 		{name: "03", args: args{subName: "The Boss Baby Family Business (2021) WEBDL-1080p.cn.ass"},
 			want:  false,
 			want1: "",
 			want2: "",
-			want3: types.Unknow,
+			want3: language.Unknown,
 			want4: ""},
 	}
 	for _, tt := range tests {
@@ -86,7 +86,7 @@ func TestFormatter_GenerateMixSubName(t *testing.T) {
 	type args struct {
 		videoFileName   string
 		subExt          string
-		subLang         types.Language
+		subLang         language.MyLanguage
 		extraSubPreName string
 	}
 	tests := []struct {
@@ -96,15 +96,15 @@ func TestFormatter_GenerateMixSubName(t *testing.T) {
 		want1 string
 		want2 string
 	}{
-		{name: "zh", args: args{videoFileName: videoFileName, subExt: common.SubExtASS, subLang: types.ChineseSimple, extraSubPreName: ""},
+		{name: "zh", args: args{videoFileName: videoFileName, subExt: common.SubExtASS, subLang: language.ChineseSimple, extraSubPreName: ""},
 			want:  videoFileNamePre + ".zh.ass",
 			want1: videoFileNamePre + ".zh.default.ass",
 			want2: videoFileNamePre + ".zh.forced.ass"},
-		{name: "zh_shooter", args: args{videoFileName: videoFileName, subExt: common.SubExtASS, subLang: types.ChineseSimple, extraSubPreName: "shooter"},
+		{name: "zh_shooter", args: args{videoFileName: videoFileName, subExt: common.SubExtASS, subLang: language.ChineseSimple, extraSubPreName: "shooter"},
 			want:  videoFileNamePre + ".zh.ass",
 			want1: videoFileNamePre + ".zh.default.ass",
 			want2: videoFileNamePre + ".zh.forced.ass"},
-		{name: "zh_shooter2", args: args{videoFileName: videoFileName, subExt: common.SubExtASS, subLang: types.ChineseSimpleEnglish, extraSubPreName: "shooter"},
+		{name: "zh_shooter2", args: args{videoFileName: videoFileName, subExt: common.SubExtASS, subLang: language.ChineseSimpleEnglish, extraSubPreName: "shooter"},
 			want:  videoFileNamePre + ".zh.ass",
 			want1: videoFileNamePre + ".zh.default.ass",
 			want2: videoFileNamePre + ".zh.forced.ass"},

+ 37 - 37
internal/pkg/sub_formatter/old/old.go

@@ -2,7 +2,7 @@ package old
 
 import (
 	"github.com/allanpk716/ChineseSubFinder/internal/common"
-	"github.com/allanpk716/ChineseSubFinder/internal/types"
+	"github.com/allanpk716/ChineseSubFinder/internal/types/language"
 	"path/filepath"
 	"strings"
 )
@@ -42,22 +42,22 @@ func IsOldVersionSubPrefixName(subFileName string) (bool, string, string) {
 	// 一种的保存了多字幕 SaveMultiSub: true
 	// 先判断 单字幕
 	switch nowExt {
-	case types.Emby_chs:
-		return true, orgMixExt, makeMixSubExtString(orgFileNameWithOutOrgMixExt, types.MatchLangChs, subTypeExt, "", true)
-	case types.Emby_cht:
-		return true, orgMixExt, makeMixSubExtString(orgFileNameWithOutOrgMixExt, types.MatchLangCht, subTypeExt, "", false)
-	case types.Emby_chs_en:
-		return true, orgMixExt, makeMixSubExtString(orgFileNameWithOutOrgMixExt, types.MatchLangChsEn, subTypeExt, "", true)
-	case types.Emby_cht_en:
-		return true, orgMixExt, makeMixSubExtString(orgFileNameWithOutOrgMixExt, types.MatchLangChtEn, subTypeExt, "", false)
-	case types.Emby_chs_jp:
-		return true, orgMixExt, makeMixSubExtString(orgFileNameWithOutOrgMixExt, types.MatchLangChsJp, subTypeExt, "", true)
-	case types.Emby_cht_jp:
-		return true, orgMixExt, makeMixSubExtString(orgFileNameWithOutOrgMixExt, types.MatchLangChtJp, subTypeExt, "", false)
-	case types.Emby_chs_kr:
-		return true, orgMixExt, makeMixSubExtString(orgFileNameWithOutOrgMixExt, types.MatchLangChsKr, subTypeExt, "", true)
-	case types.Emby_cht_kr:
-		return true, orgMixExt, makeMixSubExtString(orgFileNameWithOutOrgMixExt, types.MatchLangChtKr, subTypeExt, "", false)
+	case language.Emby_chs:
+		return true, orgMixExt, makeMixSubExtString(orgFileNameWithOutOrgMixExt, language.MatchLangChs, subTypeExt, "", true)
+	case language.Emby_cht:
+		return true, orgMixExt, makeMixSubExtString(orgFileNameWithOutOrgMixExt, language.MatchLangCht, subTypeExt, "", false)
+	case language.Emby_chs_en:
+		return true, orgMixExt, makeMixSubExtString(orgFileNameWithOutOrgMixExt, language.MatchLangChsEn, subTypeExt, "", true)
+	case language.Emby_cht_en:
+		return true, orgMixExt, makeMixSubExtString(orgFileNameWithOutOrgMixExt, language.MatchLangChtEn, subTypeExt, "", false)
+	case language.Emby_chs_jp:
+		return true, orgMixExt, makeMixSubExtString(orgFileNameWithOutOrgMixExt, language.MatchLangChsJp, subTypeExt, "", true)
+	case language.Emby_cht_jp:
+		return true, orgMixExt, makeMixSubExtString(orgFileNameWithOutOrgMixExt, language.MatchLangChtJp, subTypeExt, "", false)
+	case language.Emby_chs_kr:
+		return true, orgMixExt, makeMixSubExtString(orgFileNameWithOutOrgMixExt, language.MatchLangChsKr, subTypeExt, "", true)
+	case language.Emby_cht_kr:
+		return true, orgMixExt, makeMixSubExtString(orgFileNameWithOutOrgMixExt, language.MatchLangChtKr, subTypeExt, "", false)
 	}
 	// 再判断 多字幕情况
 	spStrings := strings.Split(nowExt, "[")
@@ -67,25 +67,25 @@ func IsOldVersionSubPrefixName(subFileName string) (bool, string, string) {
 	// 分两段来判断是否符合标准
 	// 第一段
 	firstOk := true
-	lang := types.MatchLangChs
+	lang := language.MatchLangChs
 	site := ""
 	switch spStrings[0] {
-	case types.Emby_chs:
-		lang = types.MatchLangChs
-	case types.Emby_cht:
-		lang = types.MatchLangCht
-	case types.Emby_chs_en:
-		lang = types.MatchLangChsEn
-	case types.Emby_cht_en:
-		lang = types.MatchLangChtEn
-	case types.Emby_chs_jp:
-		lang = types.MatchLangChsJp
-	case types.Emby_cht_jp:
-		lang = types.MatchLangChtJp
-	case types.Emby_chs_kr:
-		lang = types.MatchLangChsKr
-	case types.Emby_cht_kr:
-		lang = types.MatchLangChtKr
+	case language.Emby_chs:
+		lang = language.MatchLangChs
+	case language.Emby_cht:
+		lang = language.MatchLangCht
+	case language.Emby_chs_en:
+		lang = language.MatchLangChsEn
+	case language.Emby_cht_en:
+		lang = language.MatchLangChtEn
+	case language.Emby_chs_jp:
+		lang = language.MatchLangChsJp
+	case language.Emby_cht_jp:
+		lang = language.MatchLangChtJp
+	case language.Emby_chs_kr:
+		lang = language.MatchLangChsKr
+	case language.Emby_cht_kr:
+		lang = language.MatchLangChtKr
 	default:
 		firstOk = false
 	}
@@ -115,11 +115,11 @@ func makeMixSubExtString(orgFileNameWithOutExt, lang string, ext, site string, b
 
 	tmpDefault := ""
 	if beDefault == true {
-		tmpDefault = types.Emby_default
+		tmpDefault = language.Emby_default
 	}
 
 	if site == "" {
-		return orgFileNameWithOutExt + types.Emby_chinese + "(" + lang + ")" + tmpDefault + ext
+		return orgFileNameWithOutExt + language.Emby_chinese + "(" + lang + ")" + tmpDefault + ext
 	}
-	return orgFileNameWithOutExt + types.Emby_chinese + "(" + lang + "," + site + ")" + tmpDefault + ext
+	return orgFileNameWithOutExt + language.Emby_chinese + "(" + lang + "," + site + ")" + tmpDefault + ext
 }

+ 5 - 5
internal/pkg/sub_formatter/sub_format_changer.go

@@ -14,7 +14,7 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_formatter/emby"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_formatter/normal"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_helper"
-	"github.com/allanpk716/ChineseSubFinder/internal/types"
+	"github.com/allanpk716/ChineseSubFinder/internal/types/language"
 	"os"
 	"strings"
 )
@@ -109,12 +109,12 @@ func (s SubFormatChanger) autoDetectAndChange(outStruct *RenameResults, fitSubNa
 		// 转换格式后,需要保留之前的 default 或者 forced
 		findDefault := false
 		findForce := false
-		if strings.Contains(subExt, types.Sub_Ext_Mark_Default) == true {
-			subExt = strings.Replace(subExt, types.Sub_Ext_Mark_Default, "", -1)
+		if strings.Contains(subExt, language.Sub_Ext_Mark_Default) == true {
+			subExt = strings.Replace(subExt, language.Sub_Ext_Mark_Default, "", -1)
 			findDefault = true
 		}
-		if strings.Contains(subExt, types.Sub_Ext_Mark_Forced) == true {
-			subExt = strings.Replace(subExt, types.Sub_Ext_Mark_Forced, "", -1)
+		if strings.Contains(subExt, language.Sub_Ext_Mark_Forced) == true {
+			subExt = strings.Replace(subExt, language.Sub_Ext_Mark_Forced, "", -1)
 			findForce = true
 		}
 		// 通过传入的目标格式化 formatter 的名称去调用

+ 5 - 5
internal/pkg/sub_helper/sub_helper.go

@@ -8,7 +8,7 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/language"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_parser_hub"
-	"github.com/allanpk716/ChineseSubFinder/internal/types"
+	language2 "github.com/allanpk716/ChineseSubFinder/internal/types/language"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/subparser"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/supplier"
 	"github.com/go-rod/rod/lib/utils"
@@ -301,17 +301,17 @@ func SearchVideoMatchSubFileAndRemoveExtMark(oneVideoFullPath string) error {
 				continue
 			}
 			// 得包含 .default. 找个关键词
-			if strings.Contains(nowFileName, types.Sub_Ext_Mark_Default+".") == true {
+			if strings.Contains(nowFileName, language2.Sub_Ext_Mark_Default+".") == true {
 				oldPath := dir + pathSep + curFile.Name()
-				newPath := dir + pathSep + strings.ReplaceAll(curFile.Name(), types.Sub_Ext_Mark_Default+".", ".")
+				newPath := dir + pathSep + strings.ReplaceAll(curFile.Name(), language2.Sub_Ext_Mark_Default+".", ".")
 				err = os.Rename(oldPath, newPath)
 				if err != nil {
 					return err
 				}
-			} else if strings.Contains(nowFileName, types.Sub_Ext_Mark_Forced+".") == true {
+			} else if strings.Contains(nowFileName, language2.Sub_Ext_Mark_Forced+".") == true {
 				// 得包含 .forced. 找个关键词
 				oldPath := dir + pathSep + curFile.Name()
-				newPath := dir + pathSep + strings.ReplaceAll(curFile.Name(), types.Sub_Ext_Mark_Forced+".", ".")
+				newPath := dir + pathSep + strings.ReplaceAll(curFile.Name(), language2.Sub_Ext_Mark_Forced+".", ".")
 				err = os.Rename(oldPath, newPath)
 				if err != nil {
 					return err

+ 0 - 110
internal/types/language.go

@@ -1,110 +0,0 @@
-package types
-
-const (
-	// SubNameKeywordChineseSimple 用于区分字幕是简体中文还是繁体中文
-	SubNameKeywordChineseSimple = "chs"
-	SubNameKeywordTraditional   = "cht"
-)
-
-// Language 语言类型,注意,这里默认还是查找的是中文字幕,只不过下载的时候可能附带了其他的
-type Language int
-
-const (
-	Unknow                     Language = iota // 未知语言
-	ChineseSimple                              // 简体中文
-	ChineseTraditional                         // 繁体中文
-	ChineseSimpleEnglish                       // 简英双语字幕
-	ChineseTraditionalEnglish                  // 繁英双语字幕
-	English                                    // 英文
-	Japanese                                   // 日语
-	ChineseSimpleJapanese                      // 简日双语字幕
-	ChineseTraditionalJapanese                 // 繁日双语字幕
-	Korean                                     // 韩语
-	ChineseSimpleKorean                        // 简韩双语字幕
-	ChineseTraditionalKorean                   // 繁韩双语字幕
-)
-
-// 参考 https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes 标准
-const (
-	ChineseAbbr_639_1  = "zh"
-	ChineseAbbr_639_2T = "zho"
-	ChineseAbbr_639_2B = "chi"
-)
-
-// 如何 639_2B 标准的语言,暂时是用在 ffmpeg 的识别视频资源上
-const (
-	Lang_639_2B_Chinese = "chi"
-	Lang_639_2B_English = "eng"
-	Lang_639_2B_Japan   = "jpn"
-	Lang_639_2B_Korean  = "kor"
-)
-
-const (
-	Sub_Ext_Mark_Default = ".default" // 指定这个字幕是默认的
-	Sub_Ext_Mark_Forced  = ".forced"  // 指定这个字幕是强制的
-)
-
-// 需要符合 emby_helper 的格式要求,在后缀名前面
-const (
-	Emby_default = ".default" // 指定这个字幕是默认的
-	Emby_unknow  = ".unknow"  // 未知语言
-	Emby_chinese = ".chinese" // 中文
-	Emby_chi     = ".chi"     // 简体
-	Emby_chn     = ".chn"     // 中国国家代码
-	Emby_chs     = ".chs"     // 简体
-	Emby_cht     = ".cht"     // 繁体
-	Emby_chs_en  = ".chs_en"  // 简英双语字幕
-	Emby_cht_en  = ".cht_en"  // 繁英双语字幕
-	Emby_en      = ".en"      // 英文
-	Emby_jp      = ".jp"      // 日语
-	Emby_chs_jp  = ".chs_jp"  // 简日双语字幕
-	Emby_cht_jp  = ".cht_jp"  // 繁日双语字幕
-	Emby_kr      = ".kr"      // 韩语
-	Emby_chs_kr  = ".chs_kr"  // 简韩双语字幕
-	Emby_cht_kr  = ".cht_kr"  // 繁韩双语字幕
-)
-
-const (
-	MathLangChnUnknow = "未知语言"
-	MatchLangDouble   = "双语"
-	MatchLangChs      = "简"
-	MatchLangCht      = "繁"
-	MatchLangChsEn    = "简英"
-	MatchLangChtEn    = "繁英"
-	MatchLangEn       = "英"
-	MatchLangJp       = "日"
-	MatchLangChsJp    = "简日"
-	MatchLangChtJp    = "繁日"
-	MatchLangKr       = "韩"
-	MatchLangChsKr    = "简韩"
-	MatchLangChtKr    = "繁韩"
-)
-
-func (l Language) String() string {
-	switch l {
-	case ChineseSimple:
-		return MatchLangChs
-	case ChineseTraditional:
-		return MatchLangCht
-	case ChineseSimpleEnglish:
-		return MatchLangChsEn
-	case ChineseTraditionalEnglish:
-		return MatchLangChtEn
-	case English:
-		return MatchLangEn
-	case Japanese:
-		return MatchLangJp
-	case ChineseSimpleJapanese:
-		return MatchLangChsJp
-	case ChineseTraditionalJapanese:
-		return MatchLangChtJp
-	case Korean:
-		return MatchLangKr
-	case ChineseSimpleKorean:
-		return MatchLangChsKr
-	case ChineseTraditionalKorean:
-		return MatchLangChtKr
-	default:
-		return MathLangChnUnknow
-	}
-}

+ 43 - 0
internal/types/language/ISOLanguage.go

@@ -0,0 +1,43 @@
+package language
+
+// 中文语言描述
+// 参考 https://en.wikipedia.org/wiki/Chinese_Wikipedia#Automatic_conversion_between_traditional_and_simplified_Chinese_characters
+const (
+	ChineseISO_Hans = "zh-Hans" // 简体
+	ChineseISO_Hant = "zh-Hant" // 繁體
+	ChineseISO_CN   = "zh-CN"   // 大陆简体
+	ChineseISO_TW   = "zh-TW"   // 臺灣正體
+	ChineseISO_SG   = "zh-SG"   // 新加坡简体/马新简体
+	ChineseISO_MY   = "zh-MY"   // 大马简体
+	ChineseISO_HK   = "zh-HK"   // 香港繁體
+	ChineseISO_MO   = "zh-MO"   // 澳門繁體
+)
+
+// 参考 https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes 标准
+const (
+	ISO_639_1_Chinese  = "zh"
+	ISO_639_1_English  = "en"
+	ISO_639_1_Korean   = "ko"
+	ISO_639_1_Japanese = "ja"
+)
+
+const (
+	ISO_639_2T_Chinese  = "zho"
+	ISO_639_2T_English  = "eng"
+	ISO_639_2T_Korean   = "kor"
+	ISO_639_2T_Japanese = "jpn"
+)
+
+const (
+	ISO_639_2B_Chinese  = "chi"
+	ISO_639_2B_English  = "eng"
+	ISO_639_2B_Korean   = "kor"
+	ISO_639_2B_Japanese = "jpn"
+)
+
+const (
+	ISO_639_3_Chinese  = "zho"
+	ISO_639_3_English  = "eng"
+	ISO_639_3_Korean   = "kor"
+	ISO_639_3_Japanese = "jpn"
+)

+ 26 - 0
internal/types/language/language.go

@@ -0,0 +1,26 @@
+package language
+
+const (
+	Sub_Ext_Mark_Default = ".default" // 指定这个字幕是默认的
+	Sub_Ext_Mark_Forced  = ".forced"  // 指定这个字幕是强制的
+)
+
+// 需要符合 emby_helper 的格式要求,在后缀名前面
+const (
+	Emby_default = ".default" // 指定这个字幕是默认的
+	Emby_unknow  = ".unknow"  // 未知语言
+	Emby_chinese = ".chinese" // 中文
+	Emby_chi     = ".chi"     // 简体
+	Emby_chn     = ".chn"     // 中国国家代码
+	Emby_chs     = ".chs"     // 简体
+	Emby_cht     = ".cht"     // 繁体
+	Emby_chs_en  = ".chs_en"  // 简英双语字幕
+	Emby_cht_en  = ".cht_en"  // 繁英双语字幕
+	Emby_en      = ".en"      // 英文
+	Emby_jp      = ".jp"      // 日语
+	Emby_chs_jp  = ".chs_jp"  // 简日双语字幕
+	Emby_cht_jp  = ".cht_jp"  // 繁日双语字幕
+	Emby_kr      = ".kr"      // 韩语
+	Emby_chs_kr  = ".chs_kr"  // 简韩双语字幕
+	Emby_cht_kr  = ".cht_kr"  // 繁韩双语字幕
+)

+ 66 - 0
internal/types/language/my_language.go

@@ -0,0 +1,66 @@
+package language
+
+// MyLanguage 语言类型,注意,这里默认还是查找的是中文字幕,只不过下载的时候可能附带了其他的
+type MyLanguage int
+
+const (
+	Unknown                    MyLanguage = iota // 未知语言
+	ChineseSimple                                // 简体中文
+	ChineseTraditional                           // 繁体中文
+	ChineseSimpleEnglish                         // 简英双语字幕
+	ChineseTraditionalEnglish                    // 繁英双语字幕
+	English                                      // 英文
+	Japanese                                     // 日语
+	ChineseSimpleJapanese                        // 简日双语字幕
+	ChineseTraditionalJapanese                   // 繁日双语字幕
+	Korean                                       // 韩语
+	ChineseSimpleKorean                          // 简韩双语字幕
+	ChineseTraditionalKorean                     // 繁韩双语字幕
+)
+
+const (
+	MathLangChnUnknown = "未知语言"
+	MatchLangDouble    = "双语"
+	MatchLangChs       = "简"
+	MatchLangCht       = "繁"
+	MatchLangChsEn     = "简英"
+	MatchLangChtEn     = "繁英"
+	MatchLangEn        = "英"
+	MatchLangJp        = "日"
+	MatchLangChsJp     = "简日"
+	MatchLangChtJp     = "繁日"
+	MatchLangKr        = "韩"
+	MatchLangChsKr     = "简韩"
+	MatchLangChtKr     = "繁韩"
+)
+
+func (l MyLanguage) String() string {
+	switch l {
+	case ChineseSimple:
+		// 简
+		return MatchLangChs
+	case ChineseTraditional:
+		// 繁
+		return MatchLangCht
+	case ChineseSimpleEnglish:
+		return MatchLangChsEn
+	case ChineseTraditionalEnglish:
+		return MatchLangChtEn
+	case English:
+		return MatchLangEn
+	case Japanese:
+		return MatchLangJp
+	case ChineseSimpleJapanese:
+		return MatchLangChsJp
+	case ChineseTraditionalJapanese:
+		return MatchLangChtJp
+	case Korean:
+		return MatchLangKr
+	case ChineseSimpleKorean:
+		return MatchLangChsKr
+	case ChineseTraditionalKorean:
+		return MatchLangChtKr
+	default:
+		return MathLangChnUnknown
+	}
+}

+ 2 - 2
internal/types/series/info.go

@@ -1,7 +1,7 @@
 package series
 
 import (
-	"github.com/allanpk716/ChineseSubFinder/internal/types"
+	"github.com/allanpk716/ChineseSubFinder/internal/types/language"
 	"time"
 )
 
@@ -36,7 +36,7 @@ type SubInfo struct {
 	Title        string
 	Season       int
 	Episode      int
-	Language     types.Language
+	Language     language.MyLanguage
 	Dir          string // 这里需要记录字幕的位置,因为需要在同级目录匹配相应的视频才行
 	FileFullPath string // 字幕文件的全路径
 }

+ 14 - 12
internal/types/subparser/fileinfo.go

@@ -1,19 +1,21 @@
 package subparser
 
-import "github.com/allanpk716/ChineseSubFinder/internal/types"
+import (
+	"github.com/allanpk716/ChineseSubFinder/internal/types/language"
+)
 
 type FileInfo struct {
-	Content       string          // 字幕的内容
-	FromWhereSite string          // 从那个网站下载的
-	Name          string          // 字幕的名称,注意,这里需要额外的赋值,不会自动检测
-	Ext           string          // 字幕的后缀名
-	Lang          types.Language  // 识别出来的语言
-	FileFullPath  string          // 字幕文件的全路径
-	Data          []byte          // 字幕的二进制文件内容
-	Dialogues     []OneDialogue   // 整个字幕文件的所有对话
-	DialoguesEx   []OneDialogueEx // 整个字幕文件的所有对话,这里会把一句话中支持的 中、英、韩、日 四国语言给分离出来
-	CHLines       []string        // 抽取出所有的中文对话
-	OtherLines    []string        // 抽取出所有的第二语言对话,可能是英文、韩文、日文
+	Content       string              // 字幕的内容
+	FromWhereSite string              // 从那个网站下载的
+	Name          string              // 字幕的名称,注意,这里需要额外的赋值,不会自动检测
+	Ext           string              // 字幕的后缀名
+	Lang          language.MyLanguage // 识别出来的语言
+	FileFullPath  string              // 字幕文件的全路径
+	Data          []byte              // 字幕的二进制文件内容
+	Dialogues     []OneDialogue       // 整个字幕文件的所有对话
+	DialoguesEx   []OneDialogueEx     // 整个字幕文件的所有对话,这里会把一句话中支持的 中、英、韩、日 四国语言给分离出来
+	CHLines       []string            // 抽取出所有的中文对话
+	OtherLines    []string            // 抽取出所有的第二语言对话,可能是英文、韩文、日文
 }
 
 // OneDialogue 一句对话

+ 16 - 14
internal/types/supplier/subinfo.go

@@ -1,23 +1,25 @@
 package supplier
 
-import "github.com/allanpk716/ChineseSubFinder/internal/types"
+import (
+	"github.com/allanpk716/ChineseSubFinder/internal/types/language"
+)
 
 type SubInfo struct {
-	FromWhere    string         `json:"from_where"`     // 从哪个网站下载来的
-	TopN         int64          `json:"top_n"`          // 是 Top 几?
-	Name         string         `json:"name"`           // 字幕的名称,这个比较随意,优先是影片的名称,然后才是从网上下载字幕的对应名称
-	Language     types.Language `json:"language"`       // 字幕的语言
-	FileUrl      string         `json:"file-url"`       // 字幕文件下载的路径
-	Score        int64          `json:"score"`          // TODO 字幕的评分,需要有一个独立的评价体系。首先是每个网站自己的评价排序,然后再到统一的评分体系
-	Offset       int64          `json:"offset"`         // 字幕的偏移
-	Ext          string         `json:"ext"`            // 字幕文件的后缀名带点,有可能是直接能用的字幕文件,也可能是压缩包
-	Data         []byte         `json:"data"`           // 字幕文件的二进制数据
-	Season       int            `json:"season"`         // 第几季,默认-1
-	Episode      int            `json:"episode"`        // 第几集,默认-1
-	IsFullSeason bool           `json:"is_full_season"` // 是否是全季的字幕
+	FromWhere    string              `json:"from_where"`     // 从哪个网站下载来的
+	TopN         int64               `json:"top_n"`          // 是 Top 几?
+	Name         string              `json:"name"`           // 字幕的名称,这个比较随意,优先是影片的名称,然后才是从网上下载字幕的对应名称
+	Language     language.MyLanguage `json:"language"`       // 字幕的语言
+	FileUrl      string              `json:"file-url"`       // 字幕文件下载的路径
+	Score        int64               `json:"score"`          // TODO 字幕的评分,需要有一个独立的评价体系。首先是每个网站自己的评价排序,然后再到统一的评分体系
+	Offset       int64               `json:"offset"`         // 字幕的偏移
+	Ext          string              `json:"ext"`            // 字幕文件的后缀名带点,有可能是直接能用的字幕文件,也可能是压缩包
+	Data         []byte              `json:"data"`           // 字幕文件的二进制数据
+	Season       int                 `json:"season"`         // 第几季,默认-1
+	Episode      int                 `json:"episode"`        // 第几集,默认-1
+	IsFullSeason bool                `json:"is_full_season"` // 是否是全季的字幕
 }
 
-func NewSubInfo(fromWhere string, topN int64, name string, language types.Language, fileUrl string,
+func NewSubInfo(fromWhere string, topN int64, name string, language language.MyLanguage, fileUrl string,
 	score int64, offset int64, ext string, data []byte) *SubInfo {
 
 	s := SubInfo{FromWhere: fromWhere, TopN: topN, Name: name, Language: language, FileUrl: fileUrl,