easyrip 4.11.3__tar.gz → 4.13.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. {easyrip-4.11.3 → easyrip-4.13.0}/PKG-INFO +1 -1
  2. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/__init__.py +1 -10
  3. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/__main__.py +3 -1
  4. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/easyrip_command.py +29 -11
  5. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/easyrip_main.py +84 -37
  6. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/easyrip_mlang/__init__.py +2 -11
  7. easyrip-4.13.0/easyrip/easyrip_mlang/global_lang_val.py +160 -0
  8. easyrip-4.13.0/easyrip/easyrip_mlang/lang_en.py +5 -0
  9. easyrip-4.11.3/easyrip/easyrip_mlang/global_lang_val.py → easyrip-4.13.0/easyrip/easyrip_mlang/lang_tag_val.py +1 -154
  10. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/easyrip_mlang/lang_zh_Hans_CN.py +17 -15
  11. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/easyrip_mlang/translator.py +24 -29
  12. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/global_val.py +1 -1
  13. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/ripper/param.py +57 -17
  14. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/ripper/ripper.py +284 -208
  15. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/ripper/sub_and_font/ass.py +160 -0
  16. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/ripper/sub_and_font/subset.py +1 -1
  17. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip.egg-info/PKG-INFO +1 -1
  18. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip.egg-info/SOURCES.txt +1 -0
  19. easyrip-4.11.3/easyrip/easyrip_mlang/lang_en.py +0 -5
  20. {easyrip-4.11.3 → easyrip-4.13.0}/LICENSE +0 -0
  21. {easyrip-4.11.3 → easyrip-4.13.0}/README.md +0 -0
  22. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/easyrip_config/config.py +0 -0
  23. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/easyrip_config/config_key.py +0 -0
  24. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/easyrip_log.py +0 -0
  25. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/easyrip_prompt.py +0 -0
  26. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/easyrip_web/__init__.py +0 -0
  27. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/easyrip_web/http_server.py +0 -0
  28. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/easyrip_web/third_party_api.py +0 -0
  29. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/ripper/media_info.py +0 -0
  30. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/ripper/sub_and_font/__init__.py +0 -0
  31. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/ripper/sub_and_font/font.py +0 -0
  32. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip/utils.py +0 -0
  33. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip.egg-info/dependency_links.txt +0 -0
  34. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip.egg-info/entry_points.txt +0 -0
  35. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip.egg-info/requires.txt +0 -0
  36. {easyrip-4.11.3 → easyrip-4.13.0}/easyrip.egg-info/top_level.txt +0 -0
  37. {easyrip-4.11.3 → easyrip-4.13.0}/pyproject.toml +0 -0
  38. {easyrip-4.11.3 → easyrip-4.13.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: easyrip
3
- Version: 4.11.3
3
+ Version: 4.13.0
4
4
  Author: op200
5
5
  License-Expression: AGPL-3.0-or-later
6
6
  Project-URL: Homepage, https://github.com/op200/EasyRip
@@ -7,13 +7,7 @@ from .easyrip_main import (
7
7
  init,
8
8
  run_command,
9
9
  )
10
- from .easyrip_mlang import (
11
- Global_lang_val,
12
- Lang_tag,
13
- Lang_tag_language,
14
- Lang_tag_region,
15
- Lang_tag_script,
16
- )
10
+ from .easyrip_mlang import Global_lang_val, Lang_tag
17
11
  from .ripper.media_info import Media_info
18
12
  from .ripper.ripper import Ripper
19
13
  from .ripper.sub_and_font import Ass, Font, load_fonts
@@ -23,9 +17,6 @@ __all__ = [
23
17
  "Font",
24
18
  "Global_lang_val",
25
19
  "Lang_tag",
26
- "Lang_tag_language",
27
- "Lang_tag_region",
28
- "Lang_tag_script",
29
20
  "Media_info",
30
21
  "Ripper",
31
22
  "check_env",
@@ -74,6 +74,7 @@ def run() -> NoReturn:
74
74
  in {
75
75
  *Cmd_type.cd.value.names,
76
76
  *Cmd_type.mediainfo.value.names,
77
+ *Cmd_type.assinfo.value.names,
77
78
  *Cmd_type.fontinfo.value.names,
78
79
  }
79
80
  else ()
@@ -98,6 +99,7 @@ def run() -> NoReturn:
98
99
  *Opt_type._i.value.names,
99
100
  *Opt_type._o_dir.value.names,
100
101
  *Opt_type._o.value.names,
102
+ *Opt_type._pipe.value.names,
101
103
  *Opt_type._sub.value.names,
102
104
  *Opt_type._only_mux_sub_path.value.names,
103
105
  *Opt_type._soft_sub.value.names,
@@ -141,7 +143,7 @@ def run() -> NoReturn:
141
143
 
142
144
  try:
143
145
  if not run_command(command):
144
- log.warning("Stop run command")
146
+ log.warning("Command run terminated")
145
147
  except KeyboardInterrupt:
146
148
  log.warning("Manually stop run command")
147
149
 
@@ -18,7 +18,7 @@ from prompt_toolkit.document import Document
18
18
 
19
19
  from . import global_val
20
20
  from .easyrip_config.config_key import Config_key
21
- from .ripper.param import PRESET_OPT_NAME, Audio_codec, Preset_name
21
+ from .ripper.param import Audio_codec, Muxer, Preset_name
22
22
 
23
23
 
24
24
  @final
@@ -268,7 +268,6 @@ class Cmd_type(enum.Enum):
268
268
  "Translate subtitle files\n"
269
269
  "e.g. 'translate zh-Hans zh-Hant' will translate all '*.zh-Hans.ass' files into zh-Hant"
270
270
  ),
271
- childs=(Cmd_type_val(("-overwrite",)),),
272
271
  )
273
272
  mediainfo = Cmd_type_val(
274
273
  ("mediainfo",),
@@ -279,6 +278,15 @@ class Cmd_type(enum.Enum):
279
278
  Cmd_type_val(("cfd",)),
280
279
  ),
281
280
  )
281
+ assinfo = Cmd_type_val(
282
+ ("assinfo",),
283
+ param="<<path> | 'fd' | 'cfd'> [-use-libass-spec <0|1>] [-show-chars-len <0|1>]",
284
+ description="Get the ass info by the Ass class",
285
+ childs=(
286
+ Cmd_type_val(("fd",)),
287
+ Cmd_type_val(("cfd",)),
288
+ ),
289
+ )
282
290
  fontinfo = Cmd_type_val(
283
291
  ("fontinfo",),
284
292
  param="<<path> | 'fd' | 'cfd'>",
@@ -353,7 +361,8 @@ class Opt_type(enum.Enum):
353
361
  param="<string>",
354
362
  description=(
355
363
  "Setting preset\n"
356
- "Preset name:\n" # .
364
+ "\n" # .
365
+ "Preset name:\n"
357
366
  f"{Preset_name.to_help_string(' ')}"
358
367
  ),
359
368
  childs=(Cmd_type_val(tuple(Preset_name._value2member_map_)),),
@@ -442,7 +451,7 @@ class Opt_type(enum.Enum):
442
451
  'e.g. "11\\{22}33" ->\n'
443
452
  ' "11\\33" (VSFilter)\n'
444
453
  ' "11{22}33" (libass)\n'
445
- "Default: 0"
454
+ "Default: 1"
446
455
  ),
447
456
  childs=(Cmd_type_val(("0", "1")),),
448
457
  )
@@ -486,7 +495,8 @@ class Opt_type(enum.Enum):
486
495
  param="<string>",
487
496
  description=(
488
497
  "Setting audio encoder\n"
489
- "Audio encoder:\n" # .
498
+ "\n" # .
499
+ "Audio encoder:\n"
490
500
  f"{Audio_codec.to_help_string(' ')}"
491
501
  ),
492
502
  childs=(Cmd_type_val(tuple(Audio_codec._value2member_map_)),),
@@ -501,11 +511,11 @@ class Opt_type(enum.Enum):
501
511
  param="<string>",
502
512
  description=(
503
513
  "Setting muxer\n"
504
- " \n" # .
514
+ "\n" # .
505
515
  "Muxer:\n"
506
- " mp4\n"
507
- " mkv\n"
516
+ f"{Audio_codec.to_help_string(' ')}"
508
517
  ),
518
+ childs=(Cmd_type_val(tuple(Muxer._value2member_map_)),),
509
519
  )
510
520
  _r = _fps = Cmd_type_val(
511
521
  ("-r", "-fps"),
@@ -789,8 +799,10 @@ class OptCompleter(Completer):
789
799
  _preset_name = None
790
800
  if _preset in Preset_name._member_map_:
791
801
  _preset_name = Preset_name[_preset]
792
- if _preset_name is not None and _preset_name in PRESET_OPT_NAME:
793
- add_set: set[str] = {f"-{n}" for n in PRESET_OPT_NAME[_preset_name]}
802
+ if _preset_name is not None:
803
+ add_set: set[str] = {
804
+ f"-{n}" for n in _preset_name.get_param_name_set(set())
805
+ }
794
806
  add_comp_words |= add_set
795
807
  add_comp_meta_dict |= dict.fromkeys(add_set, f"{_preset} param")
796
808
 
@@ -859,7 +871,13 @@ class OptCompleter(Completer):
859
871
 
860
872
  yield from merge_completers(
861
873
  (
862
- _nested_dict_to_nc(new_nd),
874
+ merge_completers(
875
+ (
876
+ _nested_dict_to_nc(new_nd),
877
+ FuzzyCompleter(_nested_dict_to_nc(new_nd), WORD=True),
878
+ ),
879
+ deduplicate=True,
880
+ ),
863
881
  FuzzyCompleter(
864
882
  WordCompleter(
865
883
  words=tuple(opt_tree_pos_list[-1]),
@@ -30,16 +30,14 @@ from .easyrip_log import log
30
30
  from .easyrip_mlang import (
31
31
  Global_lang_val,
32
32
  Lang_tag,
33
- Lang_tag_language,
34
33
  get_system_language,
35
34
  gettext,
36
35
  translate_subtitles,
37
36
  )
38
37
  from .easyrip_prompt import easyrip_prompt
39
38
  from .ripper.media_info import Media_info
40
- from .ripper.param import DEFAULT_PRESET_PARAMS, PRESET_OPT_NAME
41
39
  from .ripper.ripper import Ripper
42
- from .ripper.sub_and_font import load_fonts
40
+ from .ripper.sub_and_font import Ass, load_fonts
43
41
  from .utils import change_title, check_ver, read_text
44
42
 
45
43
  __all__ = ["init", "run_command"]
@@ -307,6 +305,10 @@ def run_ripper_list(
307
305
  except Exception as e:
308
306
  log.error(e, deep=True)
309
307
  log.warning("Stop run Ripper")
308
+ except KeyboardInterrupt:
309
+ log.warning("Manually stop run and clear Ripper list")
310
+ Ripper.ripper_list.clear()
311
+ raise
310
312
 
311
313
  with ThreadPoolExecutor() as executor:
312
314
  for ripper in Ripper.ripper_list:
@@ -324,6 +326,10 @@ def run_ripper_list(
324
326
  except Exception as e:
325
327
  log.error(e, deep=True)
326
328
  log.warning("Stop run Ripper")
329
+ except KeyboardInterrupt:
330
+ log.warning("Manually stop run and clear Ripper list")
331
+ Ripper.ripper_list.clear()
332
+ raise
327
333
  sleep(0.5)
328
334
 
329
335
  if log.warning_num > warning_num:
@@ -419,40 +425,41 @@ def run_command(command: Iterable[str] | str) -> bool:
419
425
  log.send(_want_doc_cmd_type.value.to_doc(), is_format=False)
420
426
  elif cmd_list[2] in Ripper.Preset_name._value2member_map_:
421
427
  _preset = Ripper.Preset_name(cmd_list[2])
422
- if (
423
- _preset in DEFAULT_PRESET_PARAMS
424
- or _preset in PRESET_OPT_NAME
425
- ):
426
- if _preset in PRESET_OPT_NAME:
427
- log.send(
428
- "Params that can be directly used:\n{}",
429
- textwrap.indent(
430
- "\n".join(
431
- f"-{n}"
432
- for n in PRESET_OPT_NAME[_preset]
433
- ),
434
- prefix=" ",
435
- ),
436
- )
437
- if _preset in DEFAULT_PRESET_PARAMS:
438
- _default_params = DEFAULT_PRESET_PARAMS[_preset]
439
- max_name_len = (
440
- max(len(str(n)) for n in _default_params) + 1
441
- )
442
- log.send(
443
- "Default val:\n{}",
444
- textwrap.indent(
445
- "\n".join(
446
- f"{f'-{n}':>{max_name_len}} {v}"
447
- for n, v in _default_params.items()
448
- ),
449
- prefix=" ",
450
- ),
451
- )
452
- else:
428
+ _param_default_dict = _preset.get_param_default_dict()
429
+ _param_name_set = _preset.get_param_name_set()
430
+ if not any((_param_default_dict, _param_name_set)):
453
431
  log.send(
454
432
  "The preset '{}' has no separate help", cmd_list[2]
455
433
  )
434
+ if _param_name_set:
435
+ log.send(
436
+ "Params that can be directly used:\n{}",
437
+ textwrap.indent(
438
+ "\n".join(f"-{n}" for n in _param_name_set),
439
+ prefix=" ",
440
+ ),
441
+ )
442
+ if _param_default_dict:
443
+ max_name_len = (
444
+ max(len(str(n)) for n in _param_default_dict) + 1
445
+ )
446
+ log.send(
447
+ "Default val:\n{}",
448
+ textwrap.indent(
449
+ "\n".join(
450
+ f"{f'-{n}':>{max_name_len}} {v}"
451
+ for n, v in _param_default_dict.items()
452
+ ),
453
+ prefix=" ",
454
+ ),
455
+ )
456
+ log.send(
457
+ " FFmpeg format:\n {}",
458
+ ":".join(
459
+ f"{n}={v}"
460
+ for n, v in _param_default_dict.items()
461
+ ),
462
+ )
456
463
  else:
457
464
  log.error("'{}' is not a member of preset", cmd_list[2])
458
465
 
@@ -495,8 +502,8 @@ def run_command(command: Iterable[str] | str) -> bool:
495
502
  case Cmd_type.exit:
496
503
  sys.exit(0)
497
504
 
498
- case Cmd_type.cd | Cmd_type.mediainfo | Cmd_type.fontinfo:
499
- _path_tuple: tuple[str, ...] | None = None
505
+ case Cmd_type.cd | Cmd_type.mediainfo | Cmd_type.assinfo | Cmd_type.fontinfo:
506
+ _path_tuple: Iterable[str] | None = None
500
507
 
501
508
  match cmd_list[1]:
502
509
  case "fd" | "cfd" as fd_param:
@@ -528,6 +535,46 @@ def run_command(command: Iterable[str] | str) -> bool:
528
535
  case Cmd_type.mediainfo:
529
536
  for _path in _path_tuple:
530
537
  log.send(f"{_path}: {Media_info.from_path(_path)}")
538
+ case Cmd_type.assinfo:
539
+ USE_LIBASS_SPEC_OPT_NAME = "-use-libass-spec"
540
+ use_libass_spec: bool = True
541
+ SHOW_CHARS_LEN_OPT_NAME = "-show-chars-len"
542
+ show_chars_len: bool = False
543
+ is_use_opt: bool = False
544
+ for i, s in tuple(enumerate(cmd_list))[2:]:
545
+ if s == USE_LIBASS_SPEC_OPT_NAME:
546
+ use_libass_spec = cmd_list[i + 1] != "0"
547
+ is_use_opt = True
548
+ if s == SHOW_CHARS_LEN_OPT_NAME:
549
+ show_chars_len = cmd_list[i + 1] != "0"
550
+ is_use_opt = True
551
+ if is_use_opt:
552
+ _path_tuple = cmd_list[1:2]
553
+ log.send(
554
+ " ".join(
555
+ (
556
+ f"{USE_LIBASS_SPEC_OPT_NAME} {1 if use_libass_spec else 0}",
557
+ f"{SHOW_CHARS_LEN_OPT_NAME} {1 if show_chars_len else 0}",
558
+ )
559
+ )
560
+ )
561
+ for _path in _path_tuple:
562
+ try:
563
+ ass = Ass(_path)
564
+ except Exception as e:
565
+ log.error(e)
566
+ return False
567
+
568
+ log.send(_path)
569
+ for font_sign, ss in ass.get_font_info(
570
+ use_libass_spec=use_libass_spec,
571
+ ).items():
572
+ show_chars_len_log_str = ""
573
+ if show_chars_len:
574
+ show_chars_len_log_str = f": {len(ss)}"
575
+ log.send(
576
+ f" ( {font_sign[0]} / {font_sign[1].name} ){show_chars_len_log_str}"
577
+ )
531
578
  case Cmd_type.fontinfo:
532
579
  for _font in itertools.chain.from_iterable(
533
580
  load_fonts(_path) for _path in _path_tuple
@@ -1156,7 +1203,7 @@ def init(is_first_run: bool = False) -> None:
1156
1203
 
1157
1204
  if (
1158
1205
  lang_tag := Lang_tag.from_str(file.stem[5:])
1159
- ).language is not Lang_tag_language.Unknown:
1206
+ ).language is not Lang_tag.Language.Unknown:
1160
1207
  easyrip_mlang.all_supported_lang_map[lang_tag] = lang_map
1161
1208
 
1162
1209
  log.debug("Loading \"{}\" as '{}' language successfully", file, lang_tag)
@@ -1,22 +1,13 @@
1
1
  import locale
2
2
 
3
3
  from . import lang_en, lang_zh_Hans_CN
4
- from .global_lang_val import (
5
- Global_lang_val,
6
- Lang_tag,
7
- Lang_tag_language,
8
- Lang_tag_region,
9
- Lang_tag_script,
10
- Lang_tag_val,
11
- )
4
+ from .global_lang_val import Global_lang_val, Lang_tag
5
+ from .lang_tag_val import Lang_tag_val
12
6
  from .translator import translate_subtitles
13
7
 
14
8
  __all__ = [
15
9
  "Global_lang_val",
16
10
  "Lang_tag",
17
- "Lang_tag_language",
18
- "Lang_tag_region",
19
- "Lang_tag_script",
20
11
  "Lang_tag_val",
21
12
  "Mlang_exception",
22
13
  "get_system_language",
@@ -0,0 +1,160 @@
1
+ import enum
2
+ from collections.abc import Iterable
3
+ from dataclasses import dataclass
4
+ from typing import Self, final
5
+
6
+
7
+ @final
8
+ @dataclass(slots=True, kw_only=True)
9
+ class Lang_tag:
10
+ from .lang_tag_val import Lang_tag_language as Language
11
+ from .lang_tag_val import Lang_tag_region as Region
12
+ from .lang_tag_val import Lang_tag_script as Script
13
+
14
+ language: Language = Language.Unknown
15
+ script: Script = Script.Unknown
16
+ region: Region = Region.Unknown
17
+
18
+ class Match_priority(enum.Enum):
19
+ script = enum.auto()
20
+ region = enum.auto()
21
+
22
+ def match(
23
+ self,
24
+ target_tags: Iterable[Self],
25
+ *,
26
+ is_incomplete_match: bool = True,
27
+ priority: Match_priority = Match_priority.script,
28
+ is_allow_mismatch_language: bool = False,
29
+ ) -> Self | None:
30
+ """启用不完整匹配时,找到最匹配的第一项"""
31
+ target_tags_tuple = tuple(target_tags)
32
+ del target_tags
33
+
34
+ matching_tags_tuple = tuple(
35
+ tag for tag in target_tags_tuple if tag.language is self.language
36
+ )
37
+ if not matching_tags_tuple:
38
+ if is_allow_mismatch_language:
39
+ matching_tags_tuple = target_tags_tuple
40
+ else:
41
+ return None
42
+
43
+ if self in matching_tags_tuple:
44
+ return self
45
+ if not is_incomplete_match:
46
+ return None
47
+
48
+ same_region_tuple = tuple(
49
+ tag for tag in matching_tags_tuple if tag.region is self.region
50
+ )
51
+
52
+ same_script_tuple = tuple(
53
+ tag for tag in matching_tags_tuple if tag.script is self.script
54
+ )
55
+
56
+ if priority_same_tuple := (
57
+ same_script_tuple + same_region_tuple
58
+ if priority is self.__class__.Match_priority.script
59
+ else same_region_tuple + same_script_tuple
60
+ ):
61
+ return priority_same_tuple[0]
62
+
63
+ return matching_tags_tuple[0]
64
+
65
+ @classmethod
66
+ def from_str(
67
+ cls,
68
+ str_tag: str,
69
+ ) -> Self:
70
+ """
71
+ 输入语言标签字符串,输出标签对象
72
+
73
+ e.g. zh-Hans-CN -> Self(Language.zh, Script.Hans, Region.CN)
74
+ """
75
+ from ..easyrip_mlang import gettext
76
+
77
+ str_tag_list = str_tag.split("-")
78
+
79
+ language: Lang_tag.Language = cls.Language.from_name(str_tag_list[0])
80
+ script: Lang_tag.Script = cls.Script.Unknown
81
+ region: Lang_tag.Region = cls.Region.Unknown
82
+
83
+ for i, s in enumerate(str_tag_list[1:]):
84
+ if s in cls.Script._member_map_:
85
+ if i != 0:
86
+ raise ValueError(
87
+ gettext("The input language tag string format is illegal")
88
+ )
89
+ script = cls.Script[s]
90
+ elif s in cls.Region._member_map_:
91
+ region = cls.Region[s]
92
+
93
+ return cls(
94
+ language=language,
95
+ script=script,
96
+ region=region,
97
+ )
98
+
99
+ def __str__(self) -> str:
100
+ """返回语言标签字符串"""
101
+ if self.language == self.__class__.Language.Unknown:
102
+ raise Exception("The Language is Unknown")
103
+
104
+ res_str: str = self.language.name
105
+ if self.script != self.__class__.Script.Unknown:
106
+ res_str += f"-{self.script.name}"
107
+ if self.region != self.__class__.Region.Unknown:
108
+ res_str += f"-{self.region.name}"
109
+
110
+ return res_str
111
+
112
+ def __hash__(self) -> int:
113
+ return hash((self.language, self.script, self.region))
114
+
115
+
116
+ class Global_lang_val:
117
+ gettext_target_lang: Lang_tag = Lang_tag()
118
+
119
+ @staticmethod
120
+ def language_tag_to_local_str(language_tag: str) -> str:
121
+ from ..easyrip_mlang import gettext
122
+
123
+ tag_list = language_tag.split("-")
124
+ tag_list_len = len(tag_list)
125
+
126
+ if tag_list_len == 0:
127
+ raise Exception(gettext("The input language tag string format is illegal"))
128
+
129
+ res_str_list: list[str] = [
130
+ _local_name
131
+ if (_org_name := tag_list[0]) in Lang_tag.Language._member_map_
132
+ and (_local_name := Lang_tag.Language[_org_name].value.local_name)
133
+ else _org_name
134
+ ]
135
+
136
+ if tag_list_len >= 2:
137
+ _org_name = tag_list[1]
138
+
139
+ if _org_name in Lang_tag.Script.__members__:
140
+ _local_name = Lang_tag.Script[_org_name].value.local_name
141
+ elif _org_name in Lang_tag.Region._member_map_:
142
+ _local_name = Lang_tag.Region[_org_name].value.local_name
143
+ else:
144
+ _local_name = _org_name
145
+
146
+ res_str_list.append(_local_name)
147
+
148
+ if tag_list_len >= 3:
149
+ _org_name = tag_list[2]
150
+
151
+ if _org_name in Lang_tag.Region._member_map_:
152
+ _local_name = Lang_tag.Region[_org_name].value.local_name
153
+ else:
154
+ _local_name = _org_name
155
+
156
+ res_str_list.append(_local_name)
157
+
158
+ return (" - " if any(" " in s for s in res_str_list) else "-").join(
159
+ res_str_list
160
+ )
@@ -0,0 +1,5 @@
1
+ from .global_lang_val import Lang_tag
2
+
3
+ LANG_TAG = Lang_tag(language=Lang_tag.Language.en)
4
+
5
+ LANG_MAP: dict[str, str] = {}