mirror of
https://github.com/XiaoMi/ha_xiaomi_home.git
synced 2025-04-04 00:35:33 +08:00
Merge pull request #220 from topsworld/test_lang_integrity
test: add lang integrity check
This commit is contained in:
commit
1f20416e97
@ -43,20 +43,18 @@
|
|||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"common": {
|
"common": {
|
||||||
"-1": "未知錯誤",
|
|
||||||
"-10000": "未知錯誤",
|
"-10000": "未知錯誤",
|
||||||
"-10001": "服務不可用",
|
"-10001": "服務不可用",
|
||||||
"-10002": "無效參數",
|
"-10002": "參數無效",
|
||||||
"-10003": "資源不足",
|
"-10003": "資源不足",
|
||||||
"-10004": "內部錯誤",
|
"-10004": "內部錯誤",
|
||||||
"-10005": "權限不足",
|
"-10005": "權限不足",
|
||||||
"-10006": "執行超時",
|
"-10006": "執行超時",
|
||||||
"-10007": "設備離線或者不存在",
|
"-10007": "設備離線或者不存在",
|
||||||
"-10020": "無效的消息格式"
|
"-10020": "未授權(OAuth2)",
|
||||||
},
|
"-10030": "無效的token(HTTP)",
|
||||||
"gw": {},
|
"-10040": "無效的消息格式",
|
||||||
"lan": {},
|
"-10050": "無效的證書",
|
||||||
"cloud": {
|
|
||||||
"-704000000": "未知錯誤",
|
"-704000000": "未知錯誤",
|
||||||
"-704010000": "未授權(設備可能被刪除)",
|
"-704010000": "未授權(設備可能被刪除)",
|
||||||
"-704014006": "沒找到設備描述",
|
"-704014006": "沒找到設備描述",
|
||||||
|
@ -45,9 +45,7 @@
|
|||||||
"get_cert_error": "ゲートウェイ証明書を取得できませんでした。",
|
"get_cert_error": "ゲートウェイ証明書を取得できませんでした。",
|
||||||
"no_family_selected": "家庭が選択されていません。",
|
"no_family_selected": "家庭が選択されていません。",
|
||||||
"no_devices": "選択された家庭にデバイスがありません。デバイスがある家庭を選択して続行してください。",
|
"no_devices": "選択された家庭にデバイスがありません。デバイスがある家庭を選択して続行してください。",
|
||||||
"no_central_device": "【中央ゲートウェイモード】Home Assistant が存在する LAN 内に使用可能な Xiaomi 中央ゲートウェイがある必要があります。選択された家庭がこの要件を満たしているかどうかを確認してください。",
|
"no_central_device": "【中央ゲートウェイモード】Home Assistant が存在する LAN 内に使用可能な Xiaomi 中央ゲートウェイがある必要があります。選択された家庭がこの要件を満たしているかどうかを確認してください。"
|
||||||
"update_config_error": "設定情報の更新に失敗しました。",
|
|
||||||
"not_confirm": "変更項目が確認されていません。確認を選択してから送信してください。"
|
|
||||||
},
|
},
|
||||||
"abort": {
|
"abort": {
|
||||||
"network_connect_error": "設定に失敗しました。ネットワーク接続に異常があります。デバイスのネットワーク設定を確認してください。",
|
"network_connect_error": "設定に失敗しました。ネットワーク接続に異常があります。デバイスのネットワーク設定を確認してください。",
|
||||||
|
@ -45,14 +45,14 @@
|
|||||||
"get_cert_error": "Не удалось получить сертификат центрального шлюза.",
|
"get_cert_error": "Не удалось получить сертификат центрального шлюза.",
|
||||||
"no_family_selected": "Не выбрана домашняя сеть.",
|
"no_family_selected": "Не выбрана домашняя сеть.",
|
||||||
"no_devices": "В выбранной домашней сети нет устройств. Пожалуйста, выберите домашнюю сеть с устройствами и продолжайте.",
|
"no_devices": "В выбранной домашней сети нет устройств. Пожалуйста, выберите домашнюю сеть с устройствами и продолжайте.",
|
||||||
"no_central_device": "Для режима центрального шлюза Xiaomi необходимо наличие доступного центрального шлюза Xiaomi в локальной сети Home Assistant. Проверьте, соответствует ли выбранная домашняя сеть этому требованию.",
|
"no_central_device": "Для режима центрального шлюза Xiaomi необходимо наличие доступного центрального шлюза Xiaomi в локальной сети Home Assistant. Проверьте, соответствует ли выбранная домашняя сеть этому требованию."
|
||||||
|
},
|
||||||
"abort": {
|
"abort": {
|
||||||
"network_connect_error": "Ошибка настройки. Сетевое подключение недоступно. Проверьте настройки сети устройства.",
|
"network_connect_error": "Ошибка настройки. Сетевое подключение недоступно. Проверьте настройки сети устройства.",
|
||||||
"already_configured": "Этот пользователь уже настроен. Перейдите на страницу интеграции и нажмите кнопку «Настроить», чтобы изменить настройки.",
|
"already_configured": "Этот пользователь уже настроен. Перейдите на страницу интеграции и нажмите кнопку «Настроить», чтобы изменить настройки.",
|
||||||
"invalid_auth_info": "Информация об авторизации истекла. Перейдите на страницу интеграции и нажмите кнопку «Настроить», чтобы переавторизоваться.",
|
"invalid_auth_info": "Информация об авторизации истекла. Перейдите на страницу интеграции и нажмите кнопку «Настроить», чтобы переавторизоваться.",
|
||||||
"config_flow_error": "Ошибка настройки интеграции: {error}"
|
"config_flow_error": "Ошибка настройки интеграции: {error}"
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"step": {
|
"step": {
|
||||||
|
@ -4,8 +4,11 @@ import json
|
|||||||
from os import listdir, path
|
from os import listdir, path
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
import pytest
|
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]:
|
def load_json_file(file_path: str) -> Optional[dict]:
|
||||||
@ -20,6 +23,18 @@ def load_json_file(file_path: str) -> Optional[dict]:
|
|||||||
return None
|
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:
|
def dict_str_str(d: dict) -> bool:
|
||||||
"""restricted format: dict[str, str]"""
|
"""restricted format: dict[str, str]"""
|
||||||
if not isinstance(d, dict):
|
if not isinstance(d, dict):
|
||||||
@ -86,11 +101,35 @@ def bool_trans(d: dict) -> bool:
|
|||||||
return True
|
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
|
@pytest.mark.github
|
||||||
def test_bool_trans():
|
def test_bool_trans():
|
||||||
data: dict = load_json_file(
|
data: dict = load_json_file(
|
||||||
path.join(
|
path.join(
|
||||||
SOURCE_DIR,
|
SOURCE_PATH,
|
||||||
'../custom_components/xiaomi_home/miot/specs/bool_trans.json'))
|
'../custom_components/xiaomi_home/miot/specs/bool_trans.json'))
|
||||||
assert data
|
assert data
|
||||||
assert bool_trans(data)
|
assert bool_trans(data)
|
||||||
@ -100,7 +139,7 @@ def test_bool_trans():
|
|||||||
def test_spec_filter():
|
def test_spec_filter():
|
||||||
data: dict = load_json_file(
|
data: dict = load_json_file(
|
||||||
path.join(
|
path.join(
|
||||||
SOURCE_DIR,
|
SOURCE_PATH,
|
||||||
'../custom_components/xiaomi_home/miot/specs/spec_filter.json'))
|
'../custom_components/xiaomi_home/miot/specs/spec_filter.json'))
|
||||||
assert data
|
assert data
|
||||||
assert spec_filter(data)
|
assert spec_filter(data)
|
||||||
@ -110,7 +149,7 @@ def test_spec_filter():
|
|||||||
def test_multi_lang():
|
def test_multi_lang():
|
||||||
data: dict = load_json_file(
|
data: dict = load_json_file(
|
||||||
path.join(
|
path.join(
|
||||||
SOURCE_DIR,
|
SOURCE_PATH,
|
||||||
'../custom_components/xiaomi_home/miot/specs/multi_lang.json'))
|
'../custom_components/xiaomi_home/miot/specs/multi_lang.json'))
|
||||||
assert data
|
assert data
|
||||||
assert nested_3_dict_str_str(data)
|
assert nested_3_dict_str_str(data)
|
||||||
@ -118,10 +157,54 @@ def test_multi_lang():
|
|||||||
|
|
||||||
@pytest.mark.github
|
@pytest.mark.github
|
||||||
def test_miot_i18n():
|
def test_miot_i18n():
|
||||||
i18n_path: str = path.join(
|
i18n_path: str = path.join(SOURCE_PATH, MIOT_I18N_RELATIVE_PATH)
|
||||||
SOURCE_DIR, '../custom_components/xiaomi_home/miot/i18n')
|
|
||||||
for file_name in listdir(i18n_path):
|
for file_name in listdir(i18n_path):
|
||||||
file_path: str = path.join(i18n_path, file_name)
|
file_path: str = path.join(i18n_path, file_name)
|
||||||
data: dict = load_json_file(file_path)
|
data: dict = load_json_file(file_path)
|
||||||
assert data
|
assert data
|
||||||
assert nested_3_dict_str_str(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…
x
Reference in New Issue
Block a user