Skip to content

Commit be847cc

Browse files
committed
Merge remote-tracking branch 'u/feat(i18n)-add-ui-localization' into nightly
1 parent f01b8db commit be847cc

22 files changed

Lines changed: 305 additions & 41 deletions

crowdin.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,9 @@
1818
"en-US": "en_US"
1919
}
2020
}
21+
},
22+
{
23+
"source": "/src_assets/common/assets/web/locale/*.json",
24+
"translation": "/src_assets/common/assets/web/locale/%two_letters_code%/%original_file_name%",
2125
}
2226
]

docs/source/about/advanced_usage.rst

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,40 @@ editing the `conf` file in a text editor. Use the examples as reference.
4747
`General <https://localhost:47990/config/#general>`__
4848
-----------------------------------------------------
4949

50+
`locale <https://localhost:47990/config/#locale>`__
51+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
52+
53+
**Description**
54+
The locale used for Sunshine's user interface.
55+
56+
**Choices**
57+
58+
.. table::
59+
:widths: auto
60+
61+
======= ===========
62+
Value Description
63+
======= ===========
64+
de German
65+
en English
66+
en_GB English (UK)
67+
en_US English (United States)
68+
es Spanish
69+
fr French
70+
it Italian
71+
ru Russian
72+
sv Swedish
73+
zh Chinese (Simplified)
74+
======= ===========
75+
76+
**Default**
77+
``en``
78+
79+
**Example**
80+
.. code-block:: text
81+
82+
locale = en
83+
5084
`sunshine_name <https://localhost:47990/config/#sunshine_name>`__
5185
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5286

docs/source/contributing/localization.rst

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -30,42 +30,68 @@ localization there.
3030

3131
Extraction
3232
----------
33-
There should be minimal cases where strings need to be extracted from source code; however it may be necessary in some
34-
situations. For example if a system tray icon is added it should be localized as it is user interfacing.
3533

36-
- Wrap the string to be extracted in a function as shown.
37-
.. code-block:: cpp
34+
.. tab:: UI
3835

39-
#include <boost/locale.hpp>
40-
#include <string>
36+
Sunshine uses `Vue I18n <https://vue-i18n.intlify.dev/>`__ for localizing the UI.
37+
The following is a simple example of how to use it.
4138

42-
std::string msg = boost::locale::translate("Hello world!");
39+
- Add the string to `src_assets/common/assets/web/locale/sunshine.json` in English.
40+
.. code-block:: json
4341
44-
.. tip:: More examples can be found in the documentation for
45-
`boost locale <https://www.boost.org/doc/libs/1_70_0/libs/locale/doc/html/messages_formatting.html>`__.
42+
{
43+
"index": {
44+
"welcome": "Hello, Sunshine!"
45+
}
46+
}
4647
47-
.. warning:: This is for information only. Contributors should never include manually updated template files, or
48-
manually compiled language files in Pull Requests.
48+
- Use the string in a Vue component.
49+
.. code-block:: html
4950

50-
Strings are automatically extracted from the code to the `locale/sunshine.po` template file. The generated file is
51-
used by CrowdIn to generate language specific template files. The file is generated using the
52-
`.github/workflows/localize.yml` workflow and is run on any push event into the `nightly` branch. Jobs are only run if
53-
any of the following paths are modified.
51+
<template>
52+
<div>
53+
<p>{{ $t('index.welcome') }}</p>
54+
</div>
55+
</template>
5456

55-
.. code-block:: yaml
57+
.. tab:: C++
5658

57-
- 'src/**'
59+
There should be minimal cases where strings need to be extracted from C++ source code; however it may be necessary in
60+
some situations. For example the system tray icon could be localized as it is user interfacing.
5861

59-
When testing locally it may be desirable to manually extract, initialize, update, and compile strings. Python is
60-
required for this, along with the python dependencies in the `./scripts/requirements.txt` file. Additionally,
61-
`xgettext <https://www.gnu.org/software/gettext/>`__ must be installed.
62+
- Wrap the string to be extracted in a function as shown.
63+
.. code-block:: cpp
6264
63-
**Extract, initialize, and update**
64-
.. code-block:: bash
65+
#include <boost/locale.hpp>
66+
#include <string>
6567
66-
python ./scripts/_locale.py --extract --init --update
68+
std::string msg = boost::locale::translate("Hello world!");
6769
68-
**Compile**
69-
.. code-block:: bash
70+
.. tip:: More examples can be found in the documentation for
71+
`boost locale <https://www.boost.org/doc/libs/1_70_0/libs/locale/doc/html/messages_formatting.html>`__.
7072

71-
python ./scripts/_locale.py --compile
73+
.. warning:: This is for information only. Contributors should never include manually updated template files, or
74+
manually compiled language files in Pull Requests.
75+
76+
Strings are automatically extracted from the code to the `locale/sunshine.po` template file. The generated file is
77+
used by CrowdIn to generate language specific template files. The file is generated using the
78+
`.github/workflows/localize.yml` workflow and is run on any push event into the `nightly` branch. Jobs are only run if
79+
any of the following paths are modified.
80+
81+
.. code-block:: yaml
82+
83+
- 'src/**'
84+
85+
When testing locally it may be desirable to manually extract, initialize, update, and compile strings. Python is
86+
required for this, along with the python dependencies in the `./scripts/requirements.txt` file. Additionally,
87+
`xgettext <https://www.gnu.org/software/gettext/>`__ must be installed.
88+
89+
**Extract, initialize, and update**
90+
.. code-block:: bash
91+
92+
python ./scripts/_locale.py --extract --init --update
93+
94+
**Compile**
95+
.. code-block:: bash
96+
97+
python ./scripts/_locale.py --compile

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"bootstrap": "5.3.3",
1111
"vite": "4.5.2",
1212
"vite-plugin-ejs": "1.6.4",
13-
"vue": "3.4.5"
13+
"vue": "3.4.5",
14+
"vue-i18n": "9.10.2"
1415
}
1516
}

src/config.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,7 @@ namespace config {
450450
};
451451

452452
sunshine_t sunshine {
453+
"en", // locale
453454
2, // min_log_level
454455
0, // flags
455456
{}, // User file

src/config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ namespace config {
180180
bool on_session;
181181
};
182182
struct sunshine_t {
183+
std::string locale;
183184
int min_log_level;
184185
std::bitset<flag::FLAG_SIZE> flags;
185186
std::string credentials_file;

src_assets/common/assets/web/Navbar.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,19 @@
1414
<a class="nav-link" href="/"><i class="fas fa-fw fa-home"></i> Home</a>
1515
</li>
1616
<li class="nav-item">
17-
<a class="nav-link" href="/pin"><i class="fas fa-fw fa-unlock"></i> PIN</a>
17+
<a class="nav-link" href="/pin"><i class="fas fa-fw fa-unlock"></i> 配对</a>
1818
</li>
1919
<li class="nav-item">
20-
<a class="nav-link" href="/apps"><i class="fas fa-fw fa-stream"></i> Applications</a>
20+
<a class="nav-link" href="/apps"><i class="fas fa-fw fa-stream"></i> Games & Apps</a>
2121
</li>
2222
<li class="nav-item">
23-
<a class="nav-link" href="/config"><i class="fas fa-fw fa-cog"></i> Configuration</a>
23+
<a class="nav-link" href="/config"><i class="fas fa-fw fa-cog"></i> 设置</a>
2424
</li>
2525
<li class="nav-item">
26-
<a class="nav-link" href="/password"><i class="fas fa-fw fa-user-shield"></i> Change Password</a>
26+
<a class="nav-link" href="/password"><i class="fas fa-fw fa-user-shield"></i> 密码</a>
2727
</li>
2828
<li class="nav-item">
29-
<a class="nav-link" href="/troubleshooting"><i class="fas fa-fw fa-info"></i> Troubleshooting</a>
29+
<a class="nav-link" href="/troubleshooting"><i class="fas fa-fw fa-info"></i> 问题排查</a>
3030
</li>
3131
</ul>
3232
</div>

src_assets/common/assets/web/config.html

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,26 @@ <h1 class="my-4">Configuration</h1>
3737

3838
<!-- General Tab -->
3939
<div id="general" v-if="currentTab === 'general'" class="config-page">
40+
<!-- Locale -->
41+
<div class="mb-3">
42+
<label for="locale" class="form-label">Locale</label>
43+
<select id="locale" class="form-select" v-model="config.locale">
44+
<option value="de">German</option>
45+
<option value="en">English</option>
46+
<option value="en_GB">English (UK)</option>
47+
<option value="en_US">English (US)</option>
48+
<option value="es">Spanish</option>
49+
<option value="fr">French</option>
50+
<option value="it">Italian</option>
51+
<option value="ru">Russian</option>
52+
<option value="sv">Swedish</option>
53+
<option value="ch">Chinese Simplified</option>
54+
</select>
55+
<div class="form-text">
56+
The locale used for Sunshine's user interface.
57+
</div>
58+
</div>
59+
4060
<!-- Sunshine Name -->
4161
<div class="mb-3">
4262
<label for="sunshine_name" class="form-label">Sunshine Name</label>
@@ -1421,6 +1441,7 @@ <h2 class="accordion-header">
14211441
id: "general",
14221442
name: "General",
14231443
options: {
1444+
"locale": "en",
14241445
"sunshine_name": "",
14251446
"min_log_level": 2,
14261447
"global_prep_cmd": "[]",

src_assets/common/assets/web/index.html

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88
<body id="app">
99
<Navbar></Navbar>
1010
<div id="content" class="container">
11-
<h1 class="my-4">Hello, Sunshine!</h1>
12-
<p>Sunshine is a self-hosted game stream host for Moonlight.</p>
11+
<h1 class="my-4">{{ $t('index.welcome') }}</h1>
12+
<p>{{ $t('index.description') }}</p>
1313
<div class="alert alert-danger" v-if="fancyLogs.find(x => x.level === 'Fatal')">
1414
<div style="line-height: 32px;">
1515
<i class="fas fa-circle-exclamation" style="font-size: 32px;margin-right: 0.25em;"></i>
16-
<b>Attention!</b> Sunshine detected these errors during startup. We <b>STRONGLY RECOMMEND</b> fixing them
17-
before streaming.<br>
16+
{{ $t('index.startup_errors') }}
17+
<br>
1818
</div>
1919
<ul>
2020
<li v-for="v in fancyLogs.filter(x => x.level === 'Fatal')">{{v.value}}</li>
@@ -27,14 +27,14 @@ <h1 class="my-4">Hello, Sunshine!</h1>
2727
<h2>Version {{version}}</h2>
2828
<br>
2929
<div v-if="loading">
30-
Loading Latest Release...
30+
{{ $t('index.loading_latest') }}
3131
</div>
3232
<div class="alert alert-success" v-if="buildVersionIsDirty">
33-
Thank you for helping to make Sunshine a better software! 🌇
33+
{{ $t('index.version_dirty') }} 🌇
3434
</div>
3535
<div v-else-if="!nightlyBuildAvailable && !stableBuildAvailable && !buildVersionIsDirty">
3636
<div class="alert alert-success">
37-
You're running the latest version of Sunshine
37+
{{ $t('index.version_latest') }}
3838
</div>
3939
</div>
4040
<div v-if="nightlyBuildAvailable">
@@ -69,8 +69,40 @@ <h3>{{githubVersion.name}}</h3>
6969

7070
<script type="module">
7171
import { createApp } from 'vue'
72+
import { createI18n } from "vue-i18n";
7273
import Navbar from './Navbar.vue'
7374
import ResourceCard from './ResourceCard.vue'
75+
76+
// Import translation files (do not modify these files in git)
77+
import de from './locale/de/sunshine.json'
78+
import en from './locale/en/sunshine.json'
79+
import en_GB from './locale/en-GB/sunshine.json'
80+
import en_US from './locale/en-US/sunshine.json'
81+
import es from './locale/es/sunshine.json'
82+
import fr from './locale/fr/sunshine.json'
83+
import it from './locale/it/sunshine.json'
84+
import ru from './locale/ru/sunshine.json'
85+
import sv from './locale/sv/sunshine.json'
86+
import zh from './locale/zh/sunshine.json'
87+
88+
// Create the i18n instance
89+
const i18n = createI18n({
90+
locale: "en", // initial locale
91+
fallbackLocale: "en", // fallback locale
92+
messages: {
93+
de: de,
94+
en: en,
95+
"en-GB": en_GB,
96+
"en-US": en_US,
97+
es: es,
98+
fr: fr,
99+
it: it,
100+
ru: ru,
101+
sv: sv,
102+
zh: zh
103+
},
104+
});
105+
74106
console.log("Hello, Sunshine!")
75107
let app = createApp({
76108
components: {
@@ -155,5 +187,6 @@ <h3>{{githubVersion.name}}</h3>
155187
}
156188
}
157189
});
190+
app.use(i18n);
158191
app.mount('#app');
159192
</script>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"index": {
3+
"welcome": "",
4+
"description": "",
5+
"startup_errors": "",
6+
"loading_latest": "",
7+
"version_dirty": "",
8+
"version_latest": "",
9+
"new_nightly": "",
10+
"new_stable": "",
11+
"download": ""
12+
}
13+
}

0 commit comments

Comments
 (0)