Skip to content
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
17 changes: 17 additions & 0 deletions .github/workflows/check-code.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: Check Code

on:
pull_request:

jobs:
check-i18n:
name: Check Translation Files
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.x"

- run: python3 tests/check_i18n.py
75 changes: 75 additions & 0 deletions css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,57 @@ md-text-button .material-icons {
margin-top: 16px;
}

.lang-modal-panel {
max-width: 360px;
}

.lang-option {
display: flex;
align-items: center;
width: 100%;
padding: 12px 16px;
cursor: pointer;
border-radius: 8px;
transition: background-color 0.15s;
margin-bottom: 4px;
border: none;
background: transparent;
text-align: left;
font-family: inherit;
font-size: inherit;
}

.lang-option:focus {
outline: 2px solid #6750A4;
outline-offset: 2px;
}

.lang-option:hover {
background: rgba(103, 80, 164, 0.08);
}

.lang-option.active {
background: rgba(103, 80, 164, 0.12);
}

.lang-native {
font-size: 1rem;
font-weight: 500;
color: #1C1B1F;
flex: 1;
}

.lang-name {
font-size: 0.85rem;
color: #49454F;
margin-left: 8px;
}

.lang-check {
color: #6750A4;
font-size: 20px;
}

@media (max-width: 768px) {
.topbar-actions {
display: none;
Expand Down Expand Up @@ -644,4 +695,28 @@ md-text-button .material-icons {
--md-switch-unselected-hover-thumb-color: #605C66;
--md-switch-unselected-hover-track-color: #605C66;
}

.lang-option:hover {
background: rgba(208, 188, 255, 0.08);
}

.lang-option:focus {
outline-color: #D0BCFF;
}

.lang-option.active {
background: rgba(208, 188, 255, 0.12);
}

.lang-native {
color: #E6E0E9;
}

.lang-name {
color: #938F99;
}

.lang-check {
color: #D0BCFF;
}
}
85 changes: 65 additions & 20 deletions data/i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@
"library": "Character Library",
"about": "About",
"exeVersion": "EXE Version",
"langZh": "中文",
"langEn": "English",
"options": "Options",
"suffix": "Suffix:",
"suffixNone": "None",
"suffixMS": "Microsoft style [!]",
Expand All @@ -38,6 +35,8 @@
"historyClear": "Clear",
"historyEmpty": "No processing history yet.",
"historyCleared": "History cleared.",
"langModalTitle": "Select Language",
"langBtn": "Language",
"historyInput": "Input:",
"historyOutput": "Output:",
"libraryCharacter": "Character",
Expand All @@ -47,10 +46,10 @@
"aboutTitle": "What is Pseudo-Localization?",
"aboutContent": "Pseudolocalization (or qps-ploc, en-XA, en-XB) is a way to simulate the localization process to identify potential issues before actual translation.<br><br>During pseudo-localization, English letters are replaced with accented characters from other scripts. Separators are also added to increase string length.<br><br>Example: \"Hello\" → \"[1iaT9][ Ĥêļļø !!! ]\"<br><br>More info: <a href='https://docs.microsoft.com/en-us/globalization/methodology/pseudolocalization' target='_blank'>Microsoft Docs</a>"
},
"zh": {
"zh-Hans": {
"title": "伪本地化演示",
"modeXA": "en-XA(重音)",
"modeXB": "en-XB(反转)",
"modeXA": "en-XA (重音)",
"modeXB": "en-XB (反转)",
"inputPlaceholder": "输入要处理的文本",
"outputPlaceholder": "处理结果",
"process": "进行伪本地化!",
Expand All @@ -61,38 +60,84 @@
"library": "字符库",
"about": "关于",
"exeVersion": "EXE 版本",
"langZh": "中文",
"langEn": "English",
"options": "选项",
"suffix": "后缀:",
"suffix": "后缀:",
"suffixNone": "无",
"suffixMS": "微软式 [!]",
"suffixAndroid": "安卓式 (one two three)",
"suffixNum": "数字式 (12345)",
"suffixCustom": "自定义",
"customPrefix": "前缀",
"customSuffix": "后缀",
"customRepeat": "重复",
"customRepeatCount": "每隔N字符重复:",
"customPrefix": "前缀:",
"customSuffix": "后缀:",
"customRepeat": "重复:",
"customRepeatCount": "每隔 N 字符重复:",
"upper": "大写",
"lower": "小写",
"doubleVowel": "元音重复",
"doubleVowelCount": "元音重复次数",
"doubleVowelCount": "元音重复次数:",
"circleNumber": "处理数字",
"addHash": "添加 Hash ID",
"hashLength": "ID 长度",
"hashLength": "ID 长度:",
"preserveEsc": "保留转义字符",
"historyTitle": "历史记录",
"historyClear": "清空",
"historyEmpty": "暂无处理历史记录。",
"historyCleared": "历史记录已清空。",
"historyInput": "输入:",
"historyOutput": "输出:",
"langModalTitle": "选择语言",
"langBtn": "语言",
"historyInput": "输入:",
"historyOutput": "输出:",
"libraryCharacter": "字符",
"libraryVariants": "变体",
"libraryCount": "数量",
"libraryTotal": "共 {count} 个字符",
"aboutTitle": "什么是伪本地化?",
"aboutContent": "伪本地化 (pseudo-localization) 是一种模拟本地化过程的测试方法,可以在实际翻译前发现问题。<br><br>在伪本地化过程中,英文字母会被替换为其他语言的重音字符,还会添加分隔符以增加字符串长度。<br><br>示例:\"Hello\" → \"[1iaT9][ Ĥêļļø !!! ]\"<br><br>更多信息:<a href='https://docs.microsoft.com/zh-cn/globalization/methodology/pseudolocalization' target='_blank'>Microsoft 文档</a>"
"aboutTitle": "什么是伪本地化?",
"aboutContent": "伪本地化 (pseudo-localization) 是一种模拟本地化过程的测试方法, 可以在实际翻译前发现问题。<br><br>在伪本地化过程中, 英文字母会被替换为其他语言的重音字符, 还会添加分隔符以增加字符串长度。<br><br>示例:\"Hello\" → \"[1iaT9][ Ĥêļļø !!! ]\"<br><br>更多信息: <a href='https://docs.microsoft.com/zh-cn/globalization/methodology/pseudolocalization' target='_blank'>Microsoft 文档</a>"
},
"zh-Hant": {
"title": "偽本地化示範",
"modeXA": "en-XA (重音)",
"modeXB": "en-XB (反轉)",
"inputPlaceholder": "輸入要處理的文字",
"outputPlaceholder": "處理結果",
"process": "進行偽本地化!",
"clear": "清除",
"copy": "複製",
"copySuccess": "已複製!",
"history": "歷史記錄",
"library": "字元庫",
"about": "關於",
"exeVersion": "EXE 版本",
"suffix": "後綴:",
"suffixNone": "無",
"suffixMS": "微軟式 [!]",
"suffixAndroid": "安卓式 (one two three)",
"suffixNum": "數字式 (12345)",
"suffixCustom": "自訂",
"customPrefix": "前綴:",
"customSuffix": "後綴:",
"customRepeat": "重複:",
"customRepeatCount": "每隔 N 字元重複:",
"upper": "大寫",
"lower": "小寫",
"doubleVowel": "母音重複",
"doubleVowelCount": "母音重複次數:",
"circleNumber": "處理數字",
"addHash": "添加 Hash ID",
"hashLength": "ID 長度:",
"preserveEsc": "保留轉義字元",
"historyTitle": "歷史記錄",
"historyClear": "清除",
"historyEmpty": "暫無處理歷史記錄。",
"historyCleared": "歷史記錄已清除。",
"langModalTitle": "選擇語言",
"langBtn": "語言",
"historyInput": "輸入:",
"historyOutput": "輸出:",
"libraryCharacter": "字元",
"libraryVariants": "變體",
"libraryCount": "數量",
"libraryTotal": "共 {count} 個字元",
"aboutTitle": "什麼是偽本地化?",
"aboutContent": "偽本地化 (pseudo-localization) 是一種模擬本地化過程的測試方法,可以在實際翻譯前發現問題。<br><br>在偽本地化過程中, 英文字母會被替換為其他語言的重音字元, 還會添加分隔符以增加字串長度。<br><br>範例:\"Hello\" → \"[1iaT9][ Ĥêļļø !!! ]\"<br><br>更多資訊: <a href='https://docs.microsoft.com/zh-tw/globalization/methodology/pseudolocalization' target='_blank'>Microsoft 檔案</a>"
}
}
12 changes: 12 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
</script>
<link rel="icon" type="image/png" href="assets/icon.png" />


<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
<script type="module" src="https://unpkg.com/@material/web/all.js?module"></script>

Expand Down Expand Up @@ -201,6 +202,17 @@ <h1 id="app-title" class="app-title"></h1>
</div>
</div>

<div id="lang-modal" class="modal">
<div class="modal-backdrop" id="lang-backdrop"></div>
<div class="modal-panel lang-modal-panel">
<div class="modal-header">
<span id="lang-modal-title">Language</span>
<button class="modal-close" id="close-lang-btn"><span class="material-icons">close</span></button>
</div>
<div class="modal-content" id="lang-list"></div>
</div>
</div>

<div id="toast" class="toast"></div>

<script type="module" src="src/app.js"></script>
Expand Down
33 changes: 30 additions & 3 deletions src/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ export function initEvents() {

$("lang-btn-mobile")?.addEventListener("click", () => {
$("mobile-menu")?.classList.remove("show");
setLang(state.currentLang === "zh" ? "en" : "zh");
showModal("lang-modal");
});

$("github-btn-mobile")?.addEventListener("click", () => {
Expand All @@ -199,15 +199,42 @@ export function initEvents() {
window.open("https://github.com/suntrise/Pseudo-localization-Demo", "_blank");
});

$("lang-btn")?.addEventListener("click", () => setLang(state.currentLang === "zh" ? "en" : "zh"));
$("lang-btn")?.addEventListener("click", () => showModal("lang-modal"));

$("lang-list")?.addEventListener("click", (e) => {
const langOption = e.target.closest(".lang-option");
if (langOption) {
const selectedLang = langOption.dataset.lang;
if (selectedLang && selectedLang !== state.currentLang) {
setLang(selectedLang);
hideModal("lang-modal");
}
}
});

$("lang-list")?.addEventListener("keydown", (e) => {
if (e.key === "Enter" || e.key === " ") {
const langOption = e.target.closest(".lang-option");
if (langOption) {
e.preventDefault();
const selectedLang = langOption.dataset.lang;
if (selectedLang && selectedLang !== state.currentLang) {
setLang(selectedLang);
hideModal("lang-modal");
}
}
}
});

const modalEvents = [
["close-history-btn", "history-modal"],
["history-backdrop", "history-modal"],
["close-library-btn", "library-modal"],
["library-backdrop", "library-modal"],
["close-about-btn", "about-modal"],
["about-backdrop", "about-modal"]
["about-backdrop", "about-modal"],
["close-lang-btn", "lang-modal"],
["lang-backdrop", "lang-modal"]
];
modalEvents.forEach(([btnId, modalId]) => {
$(btnId)?.addEventListener("click", () => hideModal(modalId));
Expand Down
Loading