mirror of
https://github.com/wu736139669/hapi.git
synced 2026-10-07 19:06:11 +00:00
86 lines
4.0 KiB
Python
86 lines
4.0 KiB
Python
import copy
|
|
import io
|
|
import json
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
|
import localizations
|
|
|
|
|
|
class LocalizationTests(unittest.TestCase):
|
|
def test_check_detects_automatic_entries_without_writing(self):
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
path = Path(directory) / "Localizable.xcstrings"
|
|
data = {"sourceLanguage": "en", "strings": {"Test": {}}, "version": "1.0"}
|
|
path.write_text(json.dumps(data), encoding="utf-8")
|
|
before = path.read_bytes()
|
|
result = subprocess.run([sys.executable, localizations.__file__, "--check", str(path)], capture_output=True)
|
|
self.assertEqual(result.returncode, 1)
|
|
self.assertEqual(path.read_bytes(), before)
|
|
data["strings"]["Test"]["extractionState"] = "manual"
|
|
path.write_text(json.dumps(data), encoding="utf-8")
|
|
result = subprocess.run([sys.executable, localizations.__file__, "--check", str(path)], capture_output=True)
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
|
|
def test_duplicate_keys_are_rejected(self):
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
path = Path(directory) / "Localizable.xcstrings"
|
|
path.write_text('{"strings":{"Test":{},"Test":{}}}', encoding="utf-8")
|
|
with self.assertRaisesRegex(ValueError, "Duplicate JSON key"):
|
|
localizations.load_catalog(path)
|
|
|
|
def test_fix_preserves_concurrent_edits(self):
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
path = Path(directory) / "Localizable.xcstrings"
|
|
original = {"sourceLanguage": "en", "strings": {"Test": {}}, "version": "1.0"}
|
|
path.write_text(json.dumps(original), encoding="utf-8")
|
|
edited = json.dumps({**original, "strings": {"New edit": {}}}).encode("utf-8")
|
|
|
|
def normalize_while_editing(data):
|
|
self.assertEqual(data, original)
|
|
path.write_bytes(edited)
|
|
return b"must not overwrite the edit"
|
|
|
|
with patch.object(sys, "argv", [localizations.__file__, "--fix", str(path)]), \
|
|
patch.object(localizations, "normalize", side_effect=normalize_while_editing), \
|
|
patch.object(sys, "stderr", new_callable=io.StringIO) as stderr:
|
|
self.assertEqual(localizations.main(), 1)
|
|
self.assertIn("Catalog changed while normalizing", stderr.getvalue())
|
|
self.assertEqual(path.read_bytes(), edited)
|
|
|
|
@unittest.skipUnless(sys.platform == "darwin", "Native formatting requires Xcode")
|
|
def test_xcode_normalization_preserves_content_and_is_idempotent(self):
|
|
data = {
|
|
"sourceLanguage": "en",
|
|
"strings": {
|
|
"zebra": {"extractionState": "stale", "comment": "Keep this comment", "localizations": {
|
|
"zh-Hans": {"stringUnit": {"state": "translated", "value": "斑马 🦓\n"}},
|
|
}},
|
|
"%lld items": {"localizations": {"en": {"variations": {"plural": {
|
|
"one": {"stringUnit": {"state": "translated", "value": "%lld item"}},
|
|
"other": {"stringUnit": {"state": "translated", "value": "%lld items"}},
|
|
}}}}},
|
|
"https://example.com/a": {"shouldTranslate": False},
|
|
"Untranslated": {},
|
|
},
|
|
"version": "1.0",
|
|
}
|
|
original = copy.deepcopy(data)
|
|
first = localizations.normalize(data)
|
|
self.assertEqual(data, original)
|
|
parsed = json.loads(first)
|
|
for key, entry in original["strings"].items():
|
|
self.assertEqual(parsed["strings"][key], {**entry, "extractionState": "manual"})
|
|
self.assertEqual(set(parsed["strings"]), set(original["strings"]))
|
|
self.assertIn(b'"sourceLanguage" : "en"', first)
|
|
self.assertEqual(first, localizations.normalize(parsed))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|