Loading...
Loading...
Compare original and translation side by side
<ModuleName>/
├── Resources/
│ ├── en.lproj/Localizable.strings # Primary language (English)
│ ├── <locale>.lproj/Localizable.strings # Additional locales
│ └── ...
├── Derived/
│ └── Sources/
│ └── TuistStrings+<ModuleName>.swift # Generated by Tuist
└── Sources/
└── **/*.swift # Uses <ModuleName>Strings.Section.keytuist generate<ModuleName>/
├── Resources/
│ ├── en.lproj/Localizable.strings # 主语言(英文)
│ ├── <locale>.lproj/Localizable.strings # 其他语言区域
│ └── ...
├── Derived/
│ └── Sources/
│ └── TuistStrings+<ModuleName>.swift # 由Tuist生成
└── Sources/
└── **/*.swift # 使用<ModuleName>Strings.Section.keytuist generateundefinedundefinedundefinedundefined/* Section description */
"section.key.name" = "English value";
"section.key.withParam" = "Value with %@";"section.key.name" = "<translated value>";
"section.key.withParam" = "<translated> %@";/* 章节描述 */
"section.key.name" = "English value";
"section.key.withParam" = "Value with %@";"section.key.name" = "<translated value>";
"section.key.withParam" = "<translated> %@";tuist generateDerived/Sources/TuistStrings+<ModuleName>.swift<ModuleName>Strings.Section.keyName<ModuleName>Strings.Section.keyWithParam(value)tuist generateDerived/Sources/TuistStrings+<ModuleName>.swift<ModuleName>Strings.Section.keyName<ModuleName>Strings.Section.keyWithParam(value)| Hardcoded Pattern | Localized Pattern |
|---|---|
| |
| |
| |
| |
| 硬编码模式 | 本地化模式 |
|---|---|
| |
| |
| |
| |
Text("Settings")
.font(.headline)
TextField("Enter your name", text: $name)
Button("Submit") { ... }
Text("Hello, \(userName)!")Text(<Module>Strings.Section.settings)
.font(.headline)
TextField(<Module>Strings.Field.namePlaceholder, text: $name)
Button(<Module>Strings.Action.submit) { ... }
Text(<Module>Strings.Greeting.hello(userName))Text("Settings")
.font(.headline)
TextField("Enter your name", text: $name)
Button("Submit") { ... }
Text("Hello, \(userName)!")Text(<Module>Strings.Section.settings)
.font(.headline)
TextField(<Module>Strings.Field.namePlaceholder, text: $name)
Button(<Module>Strings.Action.submit) { ... }
Text(<Module>Strings.Greeting.hello(userName))"search.noResults" = "No results for \"%@\""// Before
Text("No results for \"\(searchText)\"")
// After
Text(<Module>Strings.Search.noResults(searchText))// Keys:
// "item.count" = "%d item"
// "item.countPlural" = "%d items"
// Swift:
let label = count == 1
? <Module>Strings.Item.count(count)
: <Module>Strings.Item.countPlural(count)"message.detail" = "%@ uploaded %d files"Text(<Module>Strings.Message.detail(userName, fileCount))"search.noResults" = "No results for \"%@\""// 转换前
Text("No results for \"\(searchText)\"")
// 转换后
Text(<Module>Strings.Search.noResults(searchText))// 键:
// "item.count" = "%d item"
// "item.countPlural" = "%d items"
// Swift代码:
let label = count == 1
? <Module>Strings.Item.count(count)
: <Module>Strings.Item.countPlural(count)"message.detail" = "%@ uploaded %d files"Text(<Module>Strings.Message.detail(userName, fileCount))python scripts/validate_strings.py /path/to/<ModuleName>python scripts/validate_strings.py /path/to/<ModuleName>search.noResultssearch.noResultspython scripts/validate_strings.py /path/to/<ModuleName>python scripts/validate_strings.py /path/to/<ModuleName>python scripts/sync_translations.py /path/to/<ModuleName> --reportpython scripts/sync_translations.py /path/to/<ModuleName> --syncpython scripts/sync_translations.py /path/to/<ModuleName> --reportpython scripts/sync_translations.py /path/to/<ModuleName> --sync"domain.context.element"<Module>Strings.Domain.Context.element"domain.context.element"<Module>Strings.Domain.Context.element| User Mental Model | Key Pattern | Generated Accessor |
|---|---|---|
| "I'm looking at my profile" | | |
| "I'm testing a build" | | |
| "I'm adding a tester" | | |
| "Something went wrong with sync" | | |
| 用户心智模型 | 键名模式 | 生成的访问器 |
|---|---|---|
| "我正在查看我的个人资料" | | |
| "我正在测试一个构建版本" | | |
| "我正在添加测试人员" | | |
| "同步时出现错误" | | |
| Bad (Technical) | Good (Domain-Focused) |
|---|---|
| |
| |
| |
| |
| |
| |
| 错误示例(技术导向) | 正确示例(领域导向) |
|---|---|
| |
| |
| |
| |
| |
| |
/* Profile Section */
"profile.title" = "Profile";
"profile.name" = "Name";
"profile.save" = "Save Changes";
"profile.saveSuccess" = "Profile updated";
/* Beta Builds */
"betaBuild.title" = "Beta Builds";
"betaBuild.whatToTest" = "What to Test";
"betaBuild.submitForReview" = "Submit for Review";
"betaBuild.expireConfirm" = "Expire this build?";
/* Tester Groups */
"testerGroup.create" = "Create Group";
"testerGroup.addTester" = "Add Tester";
"testerGroup.empty" = "No testers yet";betaBuild.submitForReview/* 个人资料章节 */
"profile.title" = "Profile";
"profile.name" = "Name";
"profile.save" = "Save Changes";
"profile.saveSuccess" = "Profile updated";
/* Beta构建版本 */
"betaBuild.title" = "Beta Builds";
"betaBuild.whatToTest" = "What to Test";
"betaBuild.submitForReview" = "Submit for Review";
"betaBuild.expireConfirm" = "Expire this build?";
/* 测试人员组 */
"testerGroup.create" = "Create Group";
"testerGroup.addTester" = "Add Tester";
"testerGroup.empty" = "No testers yet";betaBuild.submitForReview/* Comment describing the section */
"key.name" = "Value";
"key.with.parameter" = "Hello, %@!";
"key.with.number" = "%d items";
"key.with.multiple" = "%1$@ has %2$d items";\"/* 章节描述注释 */
"key.name" = "Value";
"key.with.parameter" = "Hello, %@!";
"key.with.number" = "%d items";
"key.with.multiple" = "%1$@ has %2$d items";\"