Skip to content

Commit 0a88be3

Browse files
committed
Update README
1 parent bdbf781 commit 0a88be3

File tree

2 files changed

+288
-35
lines changed

2 files changed

+288
-35
lines changed

README.md

Lines changed: 135 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,155 @@
1-
# FluentLauncher.Localization
2-
#### Fluent Launcher 的 本地化计划
1+
# Fluent Launcher Localization Project
32

4-
## 制定如下规定
3+
English | [简体中文](README_zh.md)
54

6-
首先 我们将一组对应的 `ViewModel.cs``View.xaml``View.xaml.cs` 称为一个 **视图单位**
7-
此外一些仅有的 `ViewModel.cs` 的我们也将其单独成为一个 **视图单位**
8-
如若还有一些零碎的翻译内容,我们会将其单独汇总到一些特定分类的 `.csv` 文件上
5+
This repository provides the translation resources and localization toolchain for [Fluent Launcher](https://github.com/Xcube-Studio/Natsurainko.FluentLauncher), which currently supports the following languages:
96

10-
1. 所有的语言文件均以 `.csv` 格式储存
11-
2. `.csv` 的文件名与 `View.xaml` 的文件名一致 如 `HomePage.xaml` 对应 `HomePage.csv`
12-
3. 一个 `.csv` 文件应对应一个 **视图单位** (零碎汇总除外)
13-
4. 所有的 `.csv` 必须以 UTF8-BOM 格式储存
7+
- English (en-US)
8+
- Simplified Chinese (zh-Hans)
9+
- Traditional Chinese (zh-Hant)
10+
- Russian (ru-RU)
11+
- Ukrainian (uk-UA)
1412

15-
## .csv 文件中的存储规范
13+
If you wish to add more languages, please submit a PR following [these instructions](#adding-a-language). Once the PR is accepted, support for the new language will be added in the next release.
1614

17-
`.csv` 文件中每一行的存储格式应该如下表
18-
`.csv` 文件中必须包含表头 表头如下
15+
## Translation Resources
16+
17+
All the strings in Fluent Launcher and their translations for various languages are stored in multiple `.csv` files within the `Views/` directory. To manage the large number of strings in the app efficiently, we will use the relative path to the `Views/` directory and the filename of the `.csv` file to describe the component that owns the strings in the file. During the build process of Fluent Launcher, the localization toolchain will convert these `.csv` files into PRI resources used by the WinUI app.
18+
19+
### `.csv` File Paths
20+
21+
Each `.csv` file in the `Views/` directory typically corresponds to a page in Fluent Launcher. The filename and path should match the corresponding page in [Natsurainko.FluentLauncher/Views](https://github.com/Xcube-Studio/Natsurainko.FluentLauncher/tree/main/Natsurainko.FluentLauncher/Views). Strings in these files may be used in the associated `View.xaml`, `View.xaml.cs`, or `ViewModel.cs`. For some components that only have a `ViewModel.cs`, the strings used are also stored in a separate `.csv` file.
22+
23+
Other strings used in backend code are stored in specific `.csv` files, such as `Views/Exceptions.csv` and `Views/Converters.csv`.
24+
25+
### `.csv` Content
26+
27+
The `.csv` files storing translation resources must use UTF8-BOM encoding. Each row represents a string and its translations for all supported languages. Every `.csv` file must include the following header:
1928

2029
| Id | Property | en-US | zh-Hans | zh-Hant | ru-RU | uk-UA |
21-
| ---| --- |--- | --- | --- | --- | --- |
30+
| -- | -------- | ----- | ------- | ------- | ----- | ----- |
31+
32+
33+
- `Id` and `Property` describe the string's path in the PRI resource system.
34+
35+
- If the string is only used in backend code, the `Id` field must start with an `_` prefix, and the `Property` field must be empty.
36+
37+
- Each subsequent column represents a language supported by Fluent Launcher, identified by its language code.
38+
39+
### Adding a Language
40+
41+
Clone this repository:
42+
43+
```bash
44+
git clone https://github.com/Xcube-Studio/FluentLauncher.Localization.git
45+
```
46+
47+
Add a column to the rightmost side of each `.csv` file. Enter the new language code in the header and provide translations for each row. **Do NOT** modify the content of the `Id` and `Property` columns. The headers of all `.csv` files must remain consistent.
48+
49+
You may submit a PR after completing partial translations. The Fluent Launcher build system allows missing translations. Untranslated strings will fall back to the content of the `en-US` column.
50+
51+
## WinUI 3 Localization Toolchain
52+
53+
### `.resw` Generator
54+
55+
`FluentLauncher.Infra.Localizer` is a C# command-line tool for converting all `.csv` files in the `Views/` directory into a set of `Resources.lang-<lang>.resw` files that can be used by WinUI apps, where `<lang>` is the language code of a supported language. You can also specify a default language using the `--default-language` option. Translations of the default language will be stored in the `Resources.resw` file, which will provide the default translations of strings in the app.
2256

23-
**每一行的存储中,若该行为后台代码调用,应该在 `资源Id` 部分前面加上 `_` 前缀,且该行的 `资源属性Id` 留空**
57+
Each item in a `.csv` file represetns a PRI string resource. The PRI resource ID is formatted using the following pattern:
58+
`<path_relative_to_Views_directory>_<csv_file_name>_<resourceId>/<resourcePropertyId>`.
2459

25-
| 资源Id | 资源属性Id | 英文原文 | 简体中文 | 繁体中文 | 俄文 | 烏克蘭 |
26-
| --- | --- |--- | --- | --- | --- | --- |
60+
Example: An entry in `Views/Settings/AboutPage.csv`:
2761

28-
> _不要问我为什么英文是原文,因为开发时用直接写英文可以避免一些麻烦,节省很多时间_
62+
| Id | Property | en-US | zh-Hans | zh-Hant | ru-RU | uk-UA |
63+
| -- | -------- | ----------------- | -------- | -------- | ------ | ---------- |
64+
| T1 | Text | Other information | 其它信息 | 其它信息 | Другая | информация |
2965

30-
## 开发者事宜
66+
Will output to the `.resw` file as:
3167

32-
Q: .csv 文件如何使用到项目中
33-
A: 后续我会编写一个脚本来批处理生成到对应语言文件夹的 `Resources.resw` 文件
68+
```xml
69+
<data name="Settings_AboutPage_T1.Text" xml:space="preserve">
70+
<value>Other information</value>
71+
</data>
72+
```
73+
74+
Here, `<value>` contains the translation for the corresponding language.
75+
76+
Usage of the command-line program:
77+
78+
````
79+
Description:
80+
Convert .csv files to .resw files for UWP/WinUI localization
81+
82+
Usage:
83+
FluentLauncher.Infra.Localizer [options]
3484
35-
生成例子:
85+
Options:
86+
--src <src> (REQUIRED) The source folder containing the .csv files
87+
--out <out> (REQUIRED) The output folder for .resw files
88+
--languages <languages> (REQUIRED) All languages for translation
89+
--default-language <default-language> Default language of the app []
90+
--version Show version information
91+
-?, -h, --help Show help and usage information
92+
````
3693

37-
在 Views/CoresPage.csv 中
38-
| SearchBox | PlaceholderText | Search Core | 搜索核心 | 搜索核心 | поисковое ядро | пошукове ядро |
39-
| --- | --- |--- | --- | --- | --- | --- |
94+
### `.resw` Resource Accessor Source Generator
4095

41-
`value` 为对应语言的翻译内容
42-
`name` 的拼接规则为 相对于Views文件夹的路径转换_.csv文件名字_资源Id.资源属性Id
96+
To simplify the access of PRI string resources in a WinUI project using C#, a Roslyn source generator is provided to generate the code that reads strings in the `.resw` files. The `FluentLauncher.Infra.LocalizedStrings` project provides the `GeneratedLocalizedStringsAttribute` for marking a `partial` static class, in which the string accessors will be generated as properties. Since `.resw` files are not C# source files, they need to be included as `AdditionalFiles` in the `.csproj` file of the WinUI project to allow the source generator to read them.
4397

44-
相对路径转换规则
45-
`Views/CoresPage.csv` => `CoresPage`
46-
`Views/Activities/ActivitiesNavigationPage.csv` => `Activities_ActivitiesNavigationPage`
98+
These tools can be used in any C# WinUI project by referencing the following projects:
4799

48-
在 Strings/en-Us/Resources.resw 中
100+
```xml
101+
<ItemGroup>
102+
<ProjectReference Include="..\FluentLauncher.Localization\FluentLauncher.Infra.LocalizedStrings.SourceGenerators\FluentLauncher.Infra.LocalizedStrings.SourceGenerators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
103+
<ProjectReference Include="..\FluentLauncher.Localization\FluentLauncher.Infra.LocalizedStrings\FluentLauncher.Infra.LocalizedStrings.csproj" />
104+
</ItemGroup>
49105
```
50-
<data name="CoresPage_SearchBox.PlaceholderText" xml:space="preserve">
51-
<value>Search Core</value>
52-
</data>
106+
107+
Example: If the project contains two `.resw` files:
108+
109+
- `Resources.resw` with two resources:
110+
111+
- `Button1.Content`
112+
- `Sample_Message`
113+
114+
- `TextBlocks.resw` with one resource:
115+
116+
- `DemoTextBlock.Text`
117+
118+
119+
The source generator will produce the following code:
120+
121+
```csharp
122+
[GeneratedLocalizedStrings]
123+
partial static class LocalizedStrings
124+
{
125+
private static ResourceManager s_resourceManager;
126+
private static ResourceMap s_resourceMap;
127+
128+
static LocalizedStrings()
129+
{
130+
s_resourceManager = new();
131+
s_resourceMap = s_resourceManager.MainResourceMap;
132+
}
133+
134+
// Default resource map (Resources.resw)
135+
public static string Button1_Content => s_resourceMap.GetValue("Resources/Button1/Content").ValueAsString;
136+
public static string Sample_Message => s_resourceMap.GetValue("Resources/Sample_Message").ValueAsString;
137+
138+
// Other resw files
139+
public static class TextBlocks
140+
{
141+
public static string DemoTextBlock_Text => s_resourceMap.GetValue("TextBlocks/DemoTextBlock/Text").ValueAsString;
142+
}
143+
144+
public static void UpdateLanguage()
145+
{
146+
s_resourceManager = new();
147+
s_resourceMap = s_resourceManager.MainResourceMap;
148+
}
149+
}
53150
```
54151

55-
#### 后续若还有疑问等待补充
152+
Note: `Resources.resw` provides the default resource group in WinUI, and the source generator will generates accessors as members of the class marked by `GeneratedLocalizedStrings`. For other `.resw` files, the source generator creates a nested class named after the resource group and generates accessors within it.
153+
154+
If the project contains multiple `.resw` files with the same name but different qualifiers, the source generator will prioritize the file without a qualifier. If all versions have qualifiers, the alphabetically first file name will be used for code generation.
155+

README_zh.md

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# Fluent Launcher 本地化计划
2+
3+
[English](README.md) | 简体中文
4+
5+
本仓库用于提供 [Fluent Launcher](https://github.com/Xcube-Studio/Natsurainko.FluentLauncher) 所需要的翻译资源和本地化工具链。Fluent Launcher 目前支持的语言如下:
6+
7+
- 英语 (en-US)
8+
- 简体中文 (zh-Hans)
9+
- 繁体中文 (zh-Hant)
10+
- 俄语 (ru-RU)
11+
- 乌克兰语 (uk-UA)
12+
13+
如果您希望添加更多语言,请根据[以下指示](#添加一种语言)提交 PR 。在 PR 被接受之后,我们会在下一个版本中添加对该语言的支持。
14+
15+
## 翻译资源
16+
17+
Fluent Launcher 需要的所有字符串以及对应不同语言的翻译都存储在 `Views/` 目录中的多个  `.csv`  文件中。为方便管理不同组件使用的字符串,我们使用从 `Views/` 目录开始的文件路径与文件名描述一个 `.csv` 文件对应模块的层级与名称。在构建 Fluent Launcher 时,这些 `.csv` 文件将会通过翻译工具链被转换成可以被 WinUI App 使用的 PRI 资源。
18+
19+
### `.csv` 文件路径
20+
21+
`Views/` 目录中的每个 `.csv` 文件通常对应 Fluent Launcher 的一个页面,并且该文件的文件名与路径都和该页面在 [Natsurainko.FluentLauncher/Views](https://github.com/Xcube-Studio/Natsurainko.FluentLauncher/tree/main/Natsurainko.FluentLauncher/Views) 中的路径一致。这些字符串可能在该页面对应的 `View.xaml`, `View.xaml.cs``ViewModel.cs` 中被使用。对于一些仅有 `ViewModel.cs` 的组件,其中使用的字符串也被存储在一个单独的 `.csv` 文件中。
22+
23+
后端代码中使用的其它字符串在一些特定的 `.csv` 文件存储,例如 `Views/Exceptions.csv`, `Views/Converters.csv`
24+
25+
### `.csv` 内容
26+
27+
存储翻译资源的 `.csv` 文件均使用 UTF8-BOM 编码,其中每一行表示一个字符串及其对应所有受支持语言的翻译。每个 `.csv` 文件必须包含以下表头:
28+
29+
| Id | Property | en-US | zh-Hans | zh-Hant | ru-RU | uk-UA |
30+
| -- | -------- | ----- | ------- | ------- | ----- | ----- |
31+
32+
33+
- `Id``Property` 用于描述该字符串在 PRI 资源系统中的路径。
34+
35+
- 若该字符串仅在后台代码中使用,应该在 `Id` 部分前面加上 `_` 前缀,且该行的 `Property` 必须留空。
36+
37+
- 之后的每一列表示一种 Fluent Launcher 支持的语言的语言代码。
38+
39+
### 添加一种语言
40+
41+
克隆本仓库:
42+
43+
```bash
44+
git clone https://github.com/Xcube-Studio/FluentLauncher.Localization.git
45+
```
46+
47+
在每个 `.csv` 文件的最右侧添加一列,在表头中填写新的语言代码,然后在每一行填写翻译。**请勿**修改 Id 和 Property 列的内容。所有 `.csv` 文件的表头必须保持一致。
48+
49+
您可以在完成部分翻译后提交 PR ,Fluent Launcher 的构建系统允许部分翻译的缺失,未完成翻译的字符串将会使用 en-US 列的内容显示。
50+
51+
## WinUI 3 本地化工具链
52+
53+
### `.resw` 生成器
54+
55+
`FluentLauncher.Infra.Localizer` 是一个使用 C# 编写的命令行程序,用于将 `Views/` 目录中的所有 `.csv` 文件转换为一组可以被 WinUI App 使用的 `Resources.lang-<lang>.resw` 文件。每个 `.resw` 文件对应一种语言,其中 `<lang>` 为该语言的语言代码。您也可以通过 `--default-language` 选项指定一种语言为默认语言,该语言对应的翻译将会存储在 `Resources.resw` 文件中,作为应用程序的默认语言。
56+
57+
每个 `.csv` 文件中每一项都会生成一个对应的 PRI 字符串资源。PRI 资源 ID 的生成规则为 `相对于Views目录的路径_<csv文件名字>_<资源Id>/<资源属性Id>`
58+
59+
示例:在 `Views/Settings/AboutPage.csv` 中的一项
60+
61+
| Id | Property | en-US | zh-Hans | zh-Hant | ru-RU | uk-UA |
62+
| -- | -------- | ----------------- | -------- | -------- | ------ | ---------- |
63+
| T1 | Text | Other information | 其它信息 | 其它信息 | Другая | информация |
64+
65+
对应输出的 `.resw` 文件中的 `Settings_AboutPage_T1.Text`
66+
67+
```xml
68+
<data name="Settings_AboutPage_T1.Text" xml:space="preserve">
69+
<value>Other information</value>
70+
</data>
71+
```
72+
73+
其中 `<value>` 为对应语言的翻译。
74+
75+
命令行程序的使用方法如下:
76+
77+
````
78+
Description:
79+
Convert .csv files to .resw files for UWP/WinUI localization
80+
81+
Usage:
82+
FluentLauncher.Infra.Localizer [options]
83+
84+
Options:
85+
--src <src> (REQUIRED) The source folder containing the .csv files
86+
--out <out> (REQUIRED) The output folder for .resw files
87+
--languages <languages> (REQUIRED) All languages for translation
88+
--default-language <default-language> Default language of the app []
89+
--version Show version information
90+
-?, -h, --help Show help and usage information
91+
````
92+
93+
### `.resw` 资源访问代码生成器
94+
95+
为了方便在 WinUI App 项目中使用 C# 代码读取 PRI 字符串资源,我们在 中编写了一个 Roslyn 源生成器,用于自动化读取项目中的 `.resw` 资源文件,并在一个静态类中为每个 PRI 资源生成一个属性,用于在运行时通过 `Microsoft.Windows.ApplicationModel.Resources.ResourceManager` 获取这个资源。 `FluentLauncher.Infra.LocalizedStrings` 项目提供了 `GeneratedLocalizedStringsAttribute` ,用于标记需要生成属性的 `partial` 静态类。由于 `.resw` 文件不是 C# 代码文件,为了使源生成器能够读取这些文件,我们需要在 `.csproj` 项目文件中将 `.resw` 文件指定为 `AdditionalFiles`
96+
97+
这些工具可以在任意 C# WinUI 项目中使用,只需引用这两个项目即可:
98+
99+
```xml
100+
<ItemGroup>
101+
<ProjectReference Include="..\FluentLauncher.Localization\FluentLauncher.Infra.LocalizedStrings.SourceGenerators\FluentLauncher.Infra.LocalizedStrings.SourceGenerators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
102+
<ProjectReference Include="..\FluentLauncher.Localization\FluentLauncher.Infra.LocalizedStrings\FluentLauncher.Infra.LocalizedStrings.csproj" />
103+
</ItemGroup>
104+
```
105+
106+
假设项目中存在两个 `.resw` 文件:
107+
108+
- `Resources.resw` 包含两个资源:
109+
110+
- `Button1.Content`
111+
- `Sample_Message`
112+
113+
- `TextBlocks.resw` 包含一个资源:
114+
115+
- `DemoTextBlock.Text`
116+
117+
118+
源生成器生成的代码如下:
119+
120+
```csharp
121+
[GeneratedLocalizedStrings]
122+
partial static class LocalizedStrings
123+
{
124+
private static ResourceManager s_resourceManager;
125+
private static ResourceMap s_resourceMap;
126+
127+
static LocalizedStrings()
128+
{
129+
s_resourceManager = new();
130+
s_resourceMap = s_resourceManager.MainResourceMap;
131+
}
132+
133+
// Default resource map (Resources.resw)
134+
public static string Button1_Content => s_resourceMap.GetValue("Resources/Button1/Content").ValueAsString;
135+
public static string Sample_Message => s_resourceMap.GetValue("Resources/Sample_Message").ValueAsString;
136+
137+
// Other resw files
138+
public static class TextBlocks
139+
{
140+
public static string DemoTextBlock_Text => s_resourceMap.GetValue("TextBlocks/DemoTextBlock/Text").ValueAsString;
141+
}
142+
143+
public static void UpdateLanguage()
144+
{
145+
s_resourceManager = new();
146+
s_resourceMap = s_resourceManager.MainResourceMap;
147+
}
148+
}
149+
```
150+
151+
注意:`Resources.resw` 为 WinUI 默认的资源组,所以源生成器直接在 `GeneratedLocalizedStrings` 类中生成访问器。对于其它的 `.resw` 文件,源生成器会使用资源组名称生成一个类,然后在其中生成访问器。
152+
153+
如果项目中存在多个名字相同但使用不同 Qualifer 的 `.resw` ,源生成器会默认选择不含 Qualifier 的版本。如果所有版本都含有 Qualifier ,那么其中文件名按字母排序最前的文件将会被用于代码生成。

0 commit comments

Comments
 (0)