174 lines
7.0 KiB
Python
174 lines
7.0 KiB
Python
import typing
|
|
import logging
|
|
|
|
from pydash import py_
|
|
|
|
from file import FluentFile
|
|
from fluentast import FluentAstAbstract
|
|
from fluentformatter import FluentFormatter
|
|
from project import Project
|
|
from fluent.syntax import ast, FluentParser, FluentSerializer
|
|
|
|
|
|
class RelativeFile:
|
|
def __init__(self, file: FluentFile, locale: typing.AnyStr, relative_path_from_locale: typing.AnyStr):
|
|
self.file = file
|
|
self.locale = locale
|
|
self.relative_path_from_locale = relative_path_from_locale
|
|
|
|
|
|
class FilesFinder:
|
|
def __init__(self, project: Project):
|
|
self.project: Project = project
|
|
self.created_files: typing.List[FluentFile] = []
|
|
|
|
def get_relative_path_dict(self, file: FluentFile, locale):
|
|
base_path = self.project.ru_locale_dir_path if locale == 'ru-RU' else self.project.en_locale_dir_path
|
|
return RelativeFile(
|
|
file=file,
|
|
locale=locale,
|
|
relative_path_from_locale=file.get_relative_path(base_path)
|
|
)
|
|
|
|
def get_file_pair(self, en_file: FluentFile) -> typing.Tuple[FluentFile, FluentFile]:
|
|
ru_file_path = en_file.full_path.replace('en-US', 'ru-RU')
|
|
ru_file = FluentFile(ru_file_path)
|
|
|
|
return en_file, ru_file
|
|
|
|
def execute(self):
|
|
self.created_files = []
|
|
groups = self.get_files_pars()
|
|
keys_without_pair = list(filter(lambda g: len(groups[g]) < 2, groups))
|
|
|
|
for key in keys_without_pair:
|
|
relative_file: RelativeFile = groups[key][0]
|
|
|
|
if relative_file.locale == 'en-US':
|
|
ru_file = self.create_ru_analog(relative_file)
|
|
self.created_files.append(ru_file)
|
|
elif relative_file.locale == 'ru-RU':
|
|
if not any(part in relative_file.file.full_path for part in ["robust-toolbox", "corvax", "_horizon", "_Horizon"]):
|
|
self.warn_en_analog_not_exist(relative_file)
|
|
else:
|
|
raise Exception(f'Неизвестная локаль: {relative_file.locale}')
|
|
|
|
return self.created_files
|
|
|
|
def get_files_pars(self):
|
|
en_files = self.project.get_fluent_files_by_dir(project.en_locale_dir_path)
|
|
ru_files = self.project.get_fluent_files_by_dir(project.ru_locale_dir_path)
|
|
|
|
en_rel = [self.get_relative_path_dict(f, 'en-US') for f in en_files]
|
|
ru_rel = [self.get_relative_path_dict(f, 'ru-RU') for f in ru_files]
|
|
|
|
return py_.group_by(en_rel + ru_rel, 'relative_path_from_locale')
|
|
|
|
def create_ru_analog(self, en_relative_file: RelativeFile) -> FluentFile:
|
|
ru_path = en_relative_file.file.full_path.replace('en-US', 'ru-RU')
|
|
ru_file = FluentFile(ru_path)
|
|
ru_file.save_data(en_relative_file.file.read_data())
|
|
logging.info(f'Создан файл {ru_path}')
|
|
return ru_file
|
|
|
|
def warn_en_analog_not_exist(self, ru_relative_file: RelativeFile):
|
|
file: FluentFile = ru_relative_file.file
|
|
en_path = file.full_path.replace('ru-RU', 'en-US')
|
|
logging.warning(f'Нет английского аналога: {file.full_path} → {en_path}')
|
|
|
|
|
|
class KeyFinder:
|
|
def __init__(self, files_dict):
|
|
self.files_dict = files_dict
|
|
self.changed_files: typing.List[FluentFile] = []
|
|
|
|
def execute(self) -> typing.List[FluentFile]:
|
|
self.changed_files = []
|
|
for pair in self.files_dict:
|
|
ru_file_rel = py_.find(self.files_dict[pair], {'locale': 'ru-RU'})
|
|
en_file_rel = py_.find(self.files_dict[pair], {'locale': 'en-US'})
|
|
|
|
if not ru_file_rel or not en_file_rel:
|
|
continue
|
|
|
|
self.compare_files(en_file_rel.file, ru_file_rel.file)
|
|
|
|
return self.changed_files
|
|
|
|
def compare_files(self, en_file, ru_file):
|
|
ru_parsed: ast.Resource = ru_file.parse_data(ru_file.read_data())
|
|
en_parsed: ast.Resource = en_file.parse_data(en_file.read_data())
|
|
|
|
self.write_to_ru_files(ru_file, ru_parsed, en_parsed)
|
|
self.log_not_exist_en_files(en_file, ru_parsed, en_parsed)
|
|
|
|
def write_to_ru_files(self, ru_file, ru_parsed, en_parsed):
|
|
for idx, en_msg in enumerate(en_parsed.body):
|
|
if not isinstance(en_msg, ast.Message):
|
|
continue
|
|
|
|
ru_idx = py_.find_index(ru_parsed.body, lambda msg: isinstance(msg, ast.Message) and self.find_duplicate_message_id_name(msg, en_msg))
|
|
have_changes = False
|
|
|
|
# Add new keys
|
|
if ru_idx == -1:
|
|
ru_parsed.body.insert(min(idx, len(ru_parsed.body)), en_msg)
|
|
have_changes = True
|
|
else:
|
|
ru_entry = ru_parsed.body[ru_idx]
|
|
if isinstance(ru_entry, ast.Junk):
|
|
continue
|
|
|
|
if getattr(en_msg, 'attributes', None):
|
|
if not getattr(ru_entry, 'attributes', None):
|
|
ru_entry.attributes = en_msg.attributes
|
|
have_changes = True
|
|
else:
|
|
for en_attr in en_msg.attributes:
|
|
if not py_.find(ru_entry.attributes, lambda ru_attr: ru_attr.id.name == en_attr.id.name):
|
|
ru_entry.attributes.append(en_attr)
|
|
have_changes = True
|
|
|
|
if have_changes:
|
|
serialized = serializer.serialize(ru_parsed)
|
|
self.save_and_log_file(ru_file, serialized, en_msg)
|
|
|
|
def log_not_exist_en_files(self, en_file, ru_parsed, en_parsed):
|
|
for ru_msg in ru_parsed.body:
|
|
if not isinstance(ru_msg, ast.Message):
|
|
continue
|
|
if not py_.find(en_parsed.body, lambda en_msg: self.find_duplicate_message_id_name(ru_msg, en_msg)):
|
|
logging.warning(f'Ключ "{FluentAstAbstract.get_id_name(ru_msg)}" не найден в {en_file.full_path}')
|
|
|
|
def save_and_log_file(self, file, data, msg):
|
|
file.save_data(data)
|
|
logging.info(f'Добавлен ключ: {FluentAstAbstract.get_id_name(msg)} → {file.full_path}')
|
|
self.changed_files.append(file)
|
|
|
|
def find_duplicate_message_id_name(self, a, b):
|
|
return FluentAstAbstract.get_id_name(a) == FluentAstAbstract.get_id_name(b)
|
|
|
|
|
|
######################################## Var definitions ###############################################################
|
|
|
|
logging.basicConfig(level = logging.INFO)
|
|
project = Project()
|
|
parser = FluentParser()
|
|
serializer = FluentSerializer(with_junk=True)
|
|
|
|
files_finder = FilesFinder(project)
|
|
key_finder = KeyFinder(files_finder.get_files_pars())
|
|
|
|
########################################################################################################################
|
|
|
|
print('Проверка актуальности файлов ...')
|
|
created_files = files_finder.execute()
|
|
if len(created_files):
|
|
print('Форматирование созданных файлов ...')
|
|
FluentFormatter.format(created_files)
|
|
print('Проверка актуальности ключей ...')
|
|
changed_files = key_finder.execute()
|
|
if len(changed_files):
|
|
print('Форматирование изменённых файлов ...')
|
|
FluentFormatter.format(changed_files)
|