Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add lang integrity check #220

Merged
merged 3 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions custom_components/xiaomi_home/miot/i18n/zh-Hant.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,18 @@
},
"error": {
"common": {
"-1": "未知錯誤",
"-10000": "未知錯誤",
"-10001": "服務不可用",
"-10002": "無效參數",
"-10002": "參數無效",
"-10003": "資源不足",
"-10004": "內部錯誤",
"-10005": "權限不足",
"-10006": "執行超時",
"-10007": "設備離線或者不存在",
"-10020": "無效的消息格式"
},
"gw": {},
"lan": {},
"cloud": {
"-10020": "未授權(OAuth2)",
"-10030": "無效的token(HTTP)",
"-10040": "無效的消息格式",
"-10050": "無效的證書",
"-704000000": "未知錯誤",
"-704010000": "未授權(設備可能被刪除)",
"-704014006": "沒找到設備描述",
Expand Down
4 changes: 1 addition & 3 deletions custom_components/xiaomi_home/translations/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,7 @@
"get_cert_error": "ゲートウェイ証明書を取得できませんでした。",
"no_family_selected": "家庭が選択されていません。",
"no_devices": "選択された家庭にデバイスがありません。デバイスがある家庭を選択して続行してください。",
"no_central_device": "【中央ゲートウェイモード】Home Assistant が存在する LAN 内に使用可能な Xiaomi 中央ゲートウェイがある必要があります。選択された家庭がこの要件を満たしているかどうかを確認してください。",
"update_config_error": "設定情報の更新に失敗しました。",
"not_confirm": "変更項目が確認されていません。確認を選択してから送信してください。"
"no_central_device": "【中央ゲートウェイモード】Home Assistant が存在する LAN 内に使用可能な Xiaomi 中央ゲートウェイがある必要があります。選択された家庭がこの要件を満たしているかどうかを確認してください。"
},
"abort": {
"network_connect_error": "設定に失敗しました。ネットワーク接続に異常があります。デバイスのネットワーク設定を確認してください。",
Expand Down
14 changes: 7 additions & 7 deletions custom_components/xiaomi_home/translations/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@
"get_cert_error": "Не удалось получить сертификат центрального шлюза.",
"no_family_selected": "Не выбрана домашняя сеть.",
"no_devices": "В выбранной домашней сети нет устройств. Пожалуйста, выберите домашнюю сеть с устройствами и продолжайте.",
"no_central_device": "Для режима центрального шлюза Xiaomi необходимо наличие доступного центрального шлюза Xiaomi в локальной сети Home Assistant. Проверьте, соответствует ли выбранная домашняя сеть этому требованию.",
"abort": {
"network_connect_error": "Ошибка настройки. Сетевое подключение недоступно. Проверьте настройки сети устройства.",
"already_configured": "Этот пользователь уже настроен. Перейдите на страницу интеграции и нажмите кнопку «Настроить», чтобы изменить настройки.",
"invalid_auth_info": "Информация об авторизации истекла. Перейдите на страницу интеграции и нажмите кнопку «Настроить», чтобы переавторизоваться.",
"config_flow_error": "Ошибка настройки интеграции: {error}"
}
"no_central_device": "Для режима центрального шлюза Xiaomi необходимо наличие доступного центрального шлюза Xiaomi в локальной сети Home Assistant. Проверьте, соответствует ли выбранная домашняя сеть этому требованию."
},
"abort": {
"network_connect_error": "Ошибка настройки. Сетевое подключение недоступно. Проверьте настройки сети устройства.",
"already_configured": "Этот пользователь уже настроен. Перейдите на страницу интеграции и нажмите кнопку «Настроить», чтобы изменить настройки.",
"invalid_auth_info": "Информация об авторизации истекла. Перейдите на страницу интеграции и нажмите кнопку «Настроить», чтобы переавторизоваться.",
"config_flow_error": "Ошибка настройки интеграции: {error}"
}
},
"options": {
Expand Down
95 changes: 89 additions & 6 deletions test/check_rule_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
from os import listdir, path
from typing import Optional
import pytest
import yaml

SOURCE_DIR: str = path.dirname(path.abspath(__file__))
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'


def load_json_file(file_path: str) -> Optional[dict]:
Expand All @@ -20,6 +23,18 @@ def load_json_file(file_path: str) -> Optional[dict]:
return None


def load_yaml_file(file_path: str) -> Optional[dict]:
try:
with open(file_path, 'r', encoding='utf-8') as file:
return yaml.safe_load(file)
except FileNotFoundError:
print(file_path, 'is not found.')
return None
except yaml.YAMLError:
print(file_path, 'is not a valid YAML file.')
return None


def dict_str_str(d: dict) -> bool:
"""restricted format: dict[str, str]"""
if not isinstance(d, dict):
Expand Down Expand Up @@ -86,11 +101,35 @@ def bool_trans(d: dict) -> bool:
return True


def compare_dict_structure(dict1: dict, dict2: dict) -> bool:
if not isinstance(dict1, dict) or not isinstance(dict2, dict):
print('invalid type')
return False
if dict1.keys() != dict2.keys():
print('inconsistent key values, ', dict1.keys(), dict2.keys())
return False
for key in dict1:
if isinstance(dict1[key], dict) and isinstance(dict2[key], dict):
if not compare_dict_structure(dict1[key], dict2[key]):
print('inconsistent key values, dict, ', key)
return False
elif isinstance(dict1[key], list) and isinstance(dict2[key], list):
if not all(
isinstance(i, type(j))
for i, j in zip(dict1[key], dict2[key])):
print('inconsistent key values, list, ', key)
return False
elif not isinstance(dict1[key], type(dict2[key])):
print('inconsistent key values, type, ', key)
return False
return True


@pytest.mark.github
def test_bool_trans():
data: dict = load_json_file(
path.join(
SOURCE_DIR,
SOURCE_PATH,
'../custom_components/xiaomi_home/miot/specs/bool_trans.json'))
assert data
assert bool_trans(data)
Expand All @@ -100,7 +139,7 @@ def test_bool_trans():
def test_spec_filter():
data: dict = load_json_file(
path.join(
SOURCE_DIR,
SOURCE_PATH,
'../custom_components/xiaomi_home/miot/specs/spec_filter.json'))
assert data
assert spec_filter(data)
Expand All @@ -110,18 +149,62 @@ def test_spec_filter():
def test_multi_lang():
data: dict = load_json_file(
path.join(
SOURCE_DIR,
SOURCE_PATH,
'../custom_components/xiaomi_home/miot/specs/multi_lang.json'))
assert data
assert nested_3_dict_str_str(data)


@pytest.mark.github
def test_miot_i18n():
i18n_path: str = path.join(
SOURCE_DIR, '../custom_components/xiaomi_home/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)
data: dict = load_json_file(file_path)
assert data
assert nested_3_dict_str_str(data)


@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)
data: dict = load_json_file(file_path)
assert data
assert dict_str_dict(data)


@pytest.mark.github
def test_miot_lang_integrity():
# pylint: disable=import-outside-toplevel
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)))
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)))
assert len(i18n_names) == len(translations_names)
assert i18n_names == translations_names
# Check translation files structure
default_dict: dict = load_json_file(
path.join(SOURCE_PATH, 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))
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]))
for name in list(integration_lang_list)[1:]:
compare_dict: dict = load_json_file(
path.join(SOURCE_PATH, MIOT_I18N_RELATIVE_PATH, name))
if not compare_dict_structure(default_dict, compare_dict):
print('compare_dict_structure failed /miot/i18n, ', name)
assert False
Loading