chore: Improve multi-language translation actions (#256)

* test: check bool trans integrity

* feat: add tools to update and format data

* style: sort data

* feat: update check_rule_format.py

* style: remove unuse SUPPORTED_PLATFORMS item

* test: check spec rule sort

* fix: fix py import

* feat: remove unuse code

* feat: add spec data sort
This commit is contained in:
Paul Shawn
2024-12-20 09:15:07 +08:00
committed by GitHub
parent b955c199fc
commit 571483b302
6 changed files with 341 additions and 205 deletions

View File

@ -6,9 +6,20 @@ from typing import Optional
import pytest
import yaml
SOURCE_PATH: str = path.dirname(path.abspath(__file__))
TRANS_RELATIVE_PATH: str = '../custom_components/xiaomi_home/translations'
MIOT_I18N_RELATIVE_PATH: str = '../custom_components/xiaomi_home/miot/i18n'
ROOT_PATH: str = path.dirname(path.abspath(__file__))
TRANS_RELATIVE_PATH: str = path.join(
ROOT_PATH, '../custom_components/xiaomi_home/translations')
MIOT_I18N_RELATIVE_PATH: str = path.join(
ROOT_PATH, '../custom_components/xiaomi_home/miot/i18n')
SPEC_BOOL_TRANS_FILE = path.join(
ROOT_PATH,
'../custom_components/xiaomi_home/miot/specs/bool_trans.json')
SPEC_MULTI_LANG_FILE = path.join(
ROOT_PATH,
'../custom_components/xiaomi_home/miot/specs/multi_lang.json')
SPEC_FILTER_FILE = path.join(
ROOT_PATH,
'../custom_components/xiaomi_home/miot/specs/spec_filter.json')
def load_json_file(file_path: str) -> Optional[dict]:
@ -23,6 +34,11 @@ def load_json_file(file_path: str) -> Optional[dict]:
return None
def save_json_file(file_path: str, data: dict) -> None:
with open(file_path, 'w', encoding='utf-8') as file:
json.dump(data, file, ensure_ascii=False, indent=4)
def load_yaml_file(file_path: str) -> Optional[dict]:
try:
with open(file_path, 'r', encoding='utf-8') as file:
@ -98,6 +114,16 @@ def bool_trans(d: dict) -> bool:
return False
if not nested_3_dict_str_str(d['translate']):
return False
default_trans: dict = d['translate'].pop('default')
if not default_trans:
print('default trans is empty')
return False
default_keys: set[str] = set(default_trans.keys())
for key, trans in d['translate'].items():
trans_keys: set[str] = set(trans.keys())
if set(trans.keys()) != default_keys:
print('bool trans inconsistent', key, default_keys, trans_keys)
return False
return True
@ -125,54 +151,69 @@ def compare_dict_structure(dict1: dict, dict2: dict) -> bool:
return True
def sort_bool_trans(file_path: str):
trans_data: dict = load_json_file(file_path=file_path)
trans_data['data'] = dict(sorted(trans_data['data'].items()))
for key, trans in trans_data['translate'].items():
trans_data['translate'][key] = dict(sorted(trans.items()))
return trans_data
def sort_multi_lang(file_path: str):
multi_lang: dict = load_json_file(file_path=file_path)
multi_lang = dict(sorted(multi_lang.items()))
for urn, trans in multi_lang.items():
multi_lang[urn] = dict(sorted(trans.items()))
for lang, spec in multi_lang[urn].items():
multi_lang[urn][lang] = dict(sorted(spec.items()))
return multi_lang
def sort_spec_filter(file_path: str):
filter_data: dict = load_json_file(file_path=file_path)
filter_data = dict(sorted(filter_data.items()))
for urn, spec in filter_data.items():
filter_data[urn] = dict(sorted(spec.items()))
return filter_data
@pytest.mark.github
def test_bool_trans():
data: dict = load_json_file(
path.join(
SOURCE_PATH,
'../custom_components/xiaomi_home/miot/specs/bool_trans.json'))
assert data
assert bool_trans(data)
data: dict = load_json_file(SPEC_BOOL_TRANS_FILE)
assert data, f'load {SPEC_BOOL_TRANS_FILE} failed'
assert bool_trans(data), f'{SPEC_BOOL_TRANS_FILE} format error'
@pytest.mark.github
def test_spec_filter():
data: dict = load_json_file(
path.join(
SOURCE_PATH,
'../custom_components/xiaomi_home/miot/specs/spec_filter.json'))
assert data
assert spec_filter(data)
data: dict = load_json_file(SPEC_FILTER_FILE)
assert data, f'load {SPEC_FILTER_FILE} failed'
assert spec_filter(data), f'{SPEC_FILTER_FILE} format error'
@pytest.mark.github
def test_multi_lang():
data: dict = load_json_file(
path.join(
SOURCE_PATH,
'../custom_components/xiaomi_home/miot/specs/multi_lang.json'))
assert data
assert nested_3_dict_str_str(data)
data: dict = load_json_file(SPEC_MULTI_LANG_FILE)
assert data, f'load {SPEC_MULTI_LANG_FILE} failed'
assert nested_3_dict_str_str(data), f'{SPEC_MULTI_LANG_FILE} format error'
@pytest.mark.github
def test_miot_i18n():
i18n_path: str = path.join(SOURCE_PATH, MIOT_I18N_RELATIVE_PATH)
for file_name in listdir(i18n_path):
file_path: str = path.join(i18n_path, file_name)
for file_name in listdir(MIOT_I18N_RELATIVE_PATH):
file_path: str = path.join(MIOT_I18N_RELATIVE_PATH, file_name)
data: dict = load_json_file(file_path)
assert data
assert nested_3_dict_str_str(data)
assert data, f'load {file_path} failed'
assert nested_3_dict_str_str(data), f'{file_path} format error'
@pytest.mark.github
def test_translations():
i18n_path: str = path.join(SOURCE_PATH, TRANS_RELATIVE_PATH)
for file_name in listdir(i18n_path):
file_path: str = path.join(i18n_path, file_name)
for file_name in listdir(TRANS_RELATIVE_PATH):
file_path: str = path.join(TRANS_RELATIVE_PATH, file_name)
data: dict = load_json_file(file_path)
assert data
assert dict_str_dict(data)
assert data, f'load {file_path} failed'
assert dict_str_dict(data), f'{file_path} format error'
@pytest.mark.github
@ -181,30 +222,72 @@ def test_miot_lang_integrity():
from miot.const import INTEGRATION_LANGUAGES
integration_lang_list: list[str] = [
f'{key}.json' for key in list(INTEGRATION_LANGUAGES.keys())]
translations_names: set[str] = set(listdir(
path.join(SOURCE_PATH, TRANS_RELATIVE_PATH)))
translations_names: set[str] = set(listdir(TRANS_RELATIVE_PATH))
assert len(translations_names) == len(integration_lang_list)
assert translations_names == set(integration_lang_list)
i18n_names: set[str] = set(listdir(
path.join(SOURCE_PATH, MIOT_I18N_RELATIVE_PATH)))
i18n_names: set[str] = set(listdir(MIOT_I18N_RELATIVE_PATH))
assert len(i18n_names) == len(translations_names)
assert i18n_names == translations_names
bool_trans_data: set[str] = load_json_file(SPEC_BOOL_TRANS_FILE)
bool_trans_names: set[str] = set(
bool_trans_data['translate']['default'].keys())
assert len(bool_trans_names) == len(translations_names)
# Check translation files structure
default_dict: dict = load_json_file(
path.join(SOURCE_PATH, TRANS_RELATIVE_PATH, integration_lang_list[0]))
path.join(TRANS_RELATIVE_PATH, integration_lang_list[0]))
for name in list(integration_lang_list)[1:]:
compare_dict: dict = load_json_file(
path.join(SOURCE_PATH, TRANS_RELATIVE_PATH, name))
path.join(TRANS_RELATIVE_PATH, name))
if not compare_dict_structure(default_dict, compare_dict):
print('compare_dict_structure failed /translations, ', name)
assert False
# Check i18n files structure
default_dict = load_json_file(
path.join(
SOURCE_PATH, MIOT_I18N_RELATIVE_PATH, integration_lang_list[0]))
path.join(MIOT_I18N_RELATIVE_PATH, integration_lang_list[0]))
for name in list(integration_lang_list)[1:]:
compare_dict: dict = load_json_file(
path.join(SOURCE_PATH, MIOT_I18N_RELATIVE_PATH, name))
path.join(MIOT_I18N_RELATIVE_PATH, name))
if not compare_dict_structure(default_dict, compare_dict):
print('compare_dict_structure failed /miot/i18n, ', name)
assert False
@pytest.mark.github
def test_miot_data_sort():
# pylint: disable=import-outside-toplevel
from miot.const import INTEGRATION_LANGUAGES
sort_langs: dict = dict(sorted(INTEGRATION_LANGUAGES.items()))
assert list(INTEGRATION_LANGUAGES.keys()) == list(sort_langs.keys()), (
'INTEGRATION_LANGUAGES not sorted, correct order\r\n'
f'{list(sort_langs.keys())}')
assert json.dumps(
load_json_file(file_path=SPEC_BOOL_TRANS_FILE)) == json.dumps(
sort_bool_trans(file_path=SPEC_BOOL_TRANS_FILE)), (
f'{SPEC_BOOL_TRANS_FILE} not sorted, goto project root path'
' and run the following command sorting, ',
'pytest -s -v -m update ./test/check_rule_format.py')
assert json.dumps(
load_json_file(file_path=SPEC_MULTI_LANG_FILE)) == json.dumps(
sort_multi_lang(file_path=SPEC_MULTI_LANG_FILE)), (
f'{SPEC_MULTI_LANG_FILE} not sorted, goto project root path'
' and run the following command sorting, ',
'pytest -s -v -m update ./test/check_rule_format.py')
assert json.dumps(
load_json_file(file_path=SPEC_FILTER_FILE)) == json.dumps(
sort_spec_filter(file_path=SPEC_FILTER_FILE)), (
f'{SPEC_FILTER_FILE} not sorted, goto project root path'
' and run the following command sorting, ',
'pytest -s -v -m update ./test/check_rule_format.py')
@pytest.mark.update
def test_sort_spec_data():
sort_data: dict = sort_bool_trans(file_path=SPEC_BOOL_TRANS_FILE)
save_json_file(file_path=SPEC_BOOL_TRANS_FILE, data=sort_data)
print(SPEC_BOOL_TRANS_FILE, 'formatted.')
sort_data = sort_multi_lang(file_path=SPEC_MULTI_LANG_FILE)
save_json_file(file_path=SPEC_MULTI_LANG_FILE, data=sort_data)
print(SPEC_MULTI_LANG_FILE, 'formatted.')
sort_data = sort_spec_filter(file_path=SPEC_FILTER_FILE)
save_json_file(file_path=SPEC_FILTER_FILE, data=sort_data)
print(SPEC_FILTER_FILE, 'formatted.')

View File

@ -1,3 +1,4 @@
[pytest]
markers:
github: tests for github actions
github: tests for github actions
update: update or re-sort config file