Add i18n system
This commit is contained in:
parent
d5f46925a3
commit
77be338e46
11 changed files with 340 additions and 17 deletions
71
.github/scripts/check-diff.py
vendored
Executable file
71
.github/scripts/check-diff.py
vendored
Executable file
|
|
@ -0,0 +1,71 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# SPDX-FileCopyrightText: 2019 Corentin Noël <tintou@noel.tf>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
# Taken from https://github.com/elementary/actions/blob/master/gettext-template/check-diff.py
|
||||
|
||||
import git
|
||||
import io
|
||||
|
||||
def commit_to_repo(repo):
|
||||
print('There are translation changes, committing changes to repository!')
|
||||
files = repo.git.diff(None, name_only=True)
|
||||
for f in files.split('\n'):
|
||||
if f.endswith ('.po') or f.endswith ('.pot'):
|
||||
repo.git.add(f)
|
||||
repo.git.commit('-m', 'Update translation template')
|
||||
infos = repo.remotes.origin.push()
|
||||
has_error=False
|
||||
error_msg=''
|
||||
for info in infos:
|
||||
if info.flags & git.remote.PushInfo.ERROR == git.remote.PushInfo.ERROR:
|
||||
has_error=True
|
||||
error_msg += info.summary
|
||||
if has_error:
|
||||
raise NameError('Unable to push to repository: ' + error_msg)
|
||||
|
||||
print('Checking the repository for new translations...')
|
||||
repo = git.Repo('.')
|
||||
t = repo.head.commit.tree
|
||||
files = repo.git.diff(None, name_only=True)
|
||||
needs_commit=False
|
||||
|
||||
for f in files.split('\n'):
|
||||
if f.endswith ('.pot'):
|
||||
raw_diff = repo.git.diff(t, f)
|
||||
output = io.StringIO()
|
||||
for line in raw_diff.splitlines():
|
||||
if line.startswith ('+++'):
|
||||
continue
|
||||
if line.startswith ('---'):
|
||||
continue
|
||||
if line.startswith ('diff'):
|
||||
continue
|
||||
if line.startswith ('index'):
|
||||
continue
|
||||
if line.startswith ('@@'):
|
||||
continue
|
||||
if line.startswith (' '):
|
||||
continue
|
||||
if line.startswith ('+#:'):
|
||||
continue
|
||||
if line.startswith ('-#:'):
|
||||
continue
|
||||
if line.startswith ('-"'):
|
||||
continue
|
||||
if line.startswith ('+"'):
|
||||
continue
|
||||
if not line.strip():
|
||||
continue
|
||||
print(line, file=output)
|
||||
if output.getvalue().strip():
|
||||
print(f + " has changed!")
|
||||
needs_commit = True
|
||||
output.close()
|
||||
|
||||
if needs_commit:
|
||||
commit_to_repo(repo)
|
||||
else:
|
||||
print('The translations are up-to-date!')
|
||||
62
.github/scripts/i18n.sh
vendored
Executable file
62
.github/scripts/i18n.sh
vendored
Executable file
|
|
@ -0,0 +1,62 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# SPDX-FileCopyrightText: 2019 Corentin Noël <tintou@noel.tf>
|
||||
# SPDX-FileCopyrightText: 2022 Janet Blackquill <uhhadd@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
# adapted from https://github.com/elementary/actions/blob/master/gettext-template/entrypoint.sh
|
||||
|
||||
set -e
|
||||
|
||||
export DEBIAN_FRONTEND="noninteractive"
|
||||
|
||||
# if a custom token is provided, use it instead of the default github token.
|
||||
if [ -n "$GIT_USER_TOKEN" ]; then
|
||||
GITHUB_TOKEN="$GIT_USER_TOKEN"
|
||||
fi
|
||||
|
||||
if [ -z "${GITHUB_TOKEN}" ]; then
|
||||
echo "\033[0;31mERROR: The GITHUB_TOKEN environment variable is not defined.\033[0m" && exit 1
|
||||
fi
|
||||
|
||||
# Git repository is owned by another user, mark it as safe
|
||||
git config --global --add safe.directory /github/workspace
|
||||
|
||||
# get default branch, see: https://davidwalsh.name/get-default-branch-name
|
||||
DEFAULT_BRANCH="$(git remote show origin | grep 'HEAD branch' | cut -d' ' -f5)"
|
||||
|
||||
if [ -z "${INPUT_TRANSLATION_BRANCH}" ]; then
|
||||
TRANSLATION_BRANCH="${DEFAULT_BRANCH}"
|
||||
else
|
||||
TRANSLATION_BRANCH="${INPUT_TRANSLATION_BRANCH}"
|
||||
fi
|
||||
|
||||
# default email and username to github actions user
|
||||
if [ -z "$GIT_USER_EMAIL" ]; then
|
||||
GIT_USER_EMAIL="action@github.com"
|
||||
fi
|
||||
if [ -z "$GIT_USER_NAME" ]; then
|
||||
GIT_USER_NAME="GitHub Action"
|
||||
fi
|
||||
|
||||
# make sure branches are up-to-date
|
||||
git fetch
|
||||
echo "Setting up git credentials..."
|
||||
git remote set-url origin https://x-access-token:"$GITHUB_TOKEN"@github.com/"$GITHUB_REPOSITORY".git
|
||||
git config --global user.email "$GIT_USER_EMAIL"
|
||||
git config --global user.name "$GIT_USER_NAME"
|
||||
echo "Git credentials configured."
|
||||
|
||||
# get the project's name:
|
||||
PROJECT="$(basename "$GITHUB_REPOSITORY")"
|
||||
echo "Project: $PROJECT"
|
||||
|
||||
sudo apt-get -qq update
|
||||
sudo apt-get -qq install python3-git
|
||||
|
||||
dotnet tool install --global GetText.NET.Extractor --version 1.6.6
|
||||
|
||||
GetText.Extractor --order -s TShock.sln -t i18n/template.pot
|
||||
|
||||
python3 .github/scripts/check-diff.py
|
||||
3
.github/workflows/ci-otapi3.yml
vendored
3
.github/workflows/ci-otapi3.yml
vendored
|
|
@ -33,6 +33,9 @@ jobs:
|
|||
with:
|
||||
dotnet-version: '6.0.100'
|
||||
|
||||
- name: Install msgfmt
|
||||
run: sudo apt-get install -y gettext
|
||||
|
||||
- name: Produce build
|
||||
run: |
|
||||
cd TShockLauncher
|
||||
|
|
|
|||
23
.github/workflows/i18n-extract.yml
vendored
Normal file
23
.github/workflows/i18n-extract.yml
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
name: i18n extraction
|
||||
on:
|
||||
push:
|
||||
branches: [ general-devel ]
|
||||
jobs:
|
||||
extract:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: |
|
||||
3.1.x
|
||||
6.0.100
|
||||
|
||||
- name: Run i18n checking/extraction script
|
||||
run: ./.github/scripts/i18n.sh
|
||||
shell: bash
|
||||
|
|
@ -649,7 +649,7 @@ namespace TShockAPI
|
|||
string cmdName;
|
||||
if (index == 0) // Space after the command specifier should not be supported
|
||||
{
|
||||
player.SendErrorMessage("Invalid command entered. Type {0}help for a list of valid commands.", Specifier);
|
||||
player.SendErrorMessage(I18n.C.GetString("Invalid command entered. Type {0}help for a list of valid commands.", Specifier));
|
||||
return true;
|
||||
}
|
||||
else if (index < 0)
|
||||
|
|
@ -677,28 +677,28 @@ namespace TShockAPI
|
|||
call(new CommandArgs(cmdText, player, args));
|
||||
return true;
|
||||
}
|
||||
player.SendErrorMessage("Invalid command entered. Type {0}help for a list of valid commands.", Specifier);
|
||||
player.SendErrorMessage(I18n.C.GetString("Invalid command entered. Type {0}help for a list of valid commands.", Specifier));
|
||||
return true;
|
||||
}
|
||||
foreach (Command cmd in cmds)
|
||||
{
|
||||
if (!cmd.CanRun(player))
|
||||
{
|
||||
TShock.Utils.SendLogs(string.Format("{0} tried to execute {1}{2}.", player.Name, Specifier, cmdText), Color.PaleVioletRed, player);
|
||||
player.SendErrorMessage("You do not have access to this command.");
|
||||
TShock.Utils.SendLogs(I18n.C.GetString("{0} tried to execute {1}{2}.", player.Name, Specifier, cmdText), Color.PaleVioletRed, player);
|
||||
player.SendErrorMessage(I18n.C.GetString("You do not have access to this command."));
|
||||
if (player.HasPermission(Permissions.su))
|
||||
{
|
||||
player.SendInfoMessage("You can use '{0}sudo {0}{1}' to override this check.", Specifier, cmdText);
|
||||
player.SendInfoMessage(I18n.C.GetString("You can use '{0}sudo {0}{1}' to override this check.", Specifier, cmdText));
|
||||
}
|
||||
}
|
||||
else if (!cmd.AllowServer && !player.RealPlayer)
|
||||
{
|
||||
player.SendErrorMessage("You must use this command in-game.");
|
||||
player.SendErrorMessage(I18n.C.GetString("You must use this command in-game."));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cmd.DoLog)
|
||||
TShock.Utils.SendLogs(string.Format("{0} executed: {1}{2}.", player.Name, silent ? SilentSpecifier : Specifier, cmdText), Color.PaleVioletRed, player);
|
||||
TShock.Utils.SendLogs(I18n.C.GetString("{0} executed: {1}{2}.", player.Name, silent ? SilentSpecifier : Specifier, cmdText), Color.PaleVioletRed, player);
|
||||
cmd.Run(cmdText, silent, player, args);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
46
TShockAPI/I18n.cs
Normal file
46
TShockAPI/I18n.cs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2022 Janet Blackquill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using GetText;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
static class I18n {
|
||||
static string TranslationsDirectory => Path.Combine(AppContext.BaseDirectory, "i18n");
|
||||
static CultureInfo TranslationCultureInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
// cross-platform mapping of cultureinfos can be a bit screwy, so give our users
|
||||
// the chance to explicitly spell out which translation they would like to use.
|
||||
// this is an environment variable instead of a flag because this needs to be
|
||||
// valid whether the passed flags are in a sane state or not.
|
||||
if (Environment.GetEnvironmentVariable("TSHOCK_LANGUAGE") is string overrideLang)
|
||||
{
|
||||
return new CultureInfo(overrideLang);
|
||||
}
|
||||
return CultureInfo.CurrentUICulture;
|
||||
}
|
||||
}
|
||||
/// <value>Instance of a <c>GetText.Catalog</c> loaded with TShockAPI translations for user's specified language</value>
|
||||
public static Catalog C = new Catalog("TShockAPI", TranslationsDirectory, TranslationCultureInfo);
|
||||
}
|
||||
}
|
||||
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
||||
<PackageReference Include="GetText.NET" Version="1.6.6" />
|
||||
<PackageReference Include="MySql.Data" Version="8.0.31" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.10" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
<PackageReference Include="MySql.Data" Version="8.0.31" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.10" />
|
||||
<PackageReference Include="ModFramework" Version="1.1.6" GeneratePathProperty="true" /> <!-- only used to extract out to ./bin. -->
|
||||
<PackageReference Include="GetText.NET" Version="1.6.6" /> <!-- only used to extract out to ./bin. -->
|
||||
|
||||
<!-- the launcher doesnt need the direct OTAPI reference, but since PackageReference[ExcludeFromSingleFile] doesnt work, exclude the assets and copy manually -->
|
||||
<PackageReference Include="OTAPI.Upcoming" Version="3.1.14" ExcludeAssets="all" GeneratePathProperty="true" />
|
||||
|
|
@ -41,6 +42,31 @@
|
|||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="CheckMsgfmtCallable">
|
||||
<Exec Command="msgfmt --help > NUL" IgnoreExitCode="True" Condition=" '$(OS)' == 'Windows_NT' ">
|
||||
<Output TaskParameter="ExitCode" PropertyName="MsgfmtExitCode" />
|
||||
</Exec>
|
||||
<Exec Command="msgfmt --help 2>/dev/null >/dev/null" IgnoreExitCode="True" Condition=" '$(OS)' != 'Windows_NT' ">
|
||||
<Output TaskParameter="ExitCode" PropertyName="MsgfmtExitCode" />
|
||||
</Exec>
|
||||
</Target>
|
||||
|
||||
<!-- The condition for a Target can't come from the values of another target, so instead we have to put the same condition on all three of the items inside. -->
|
||||
<Target
|
||||
Name="GenerateMOFiles"
|
||||
DependsOnTargets="CheckMsgfmtCallable"
|
||||
AfterTargets="PostBuildEvent;Publish"
|
||||
Inputs="..\i18n\**\*.po"
|
||||
Outputs="$(OutDir)i18n\**\*.mo">
|
||||
<ItemGroup Condition="'$(MsgfmtExitCode)' == '0'">
|
||||
<POFiles Include="..\i18n\**\*.po" />
|
||||
</ItemGroup>
|
||||
<MakeDir Directories="$(OutDir)i18n/%(POFiles.RecursiveDir)" Condition="'$(MsgfmtExitCode)' == '0'" />
|
||||
<Exec Command="msgfmt -o $(OutDir)i18n/%(RecursiveDir)%(Filename).mo @(POFiles)" Outputs="$(OutDir)i18n\**\*.mo" Condition="'$(MsgfmtExitCode)' == '0'">
|
||||
<Output ItemName="Generated" TaskParameter="Outputs"/>
|
||||
</Exec>
|
||||
</Target>
|
||||
|
||||
<Target Name="CreateServerPlugins" AfterTargets="PostBuildEvent;Publish">
|
||||
<MakeDir Directories="$(OutDir)ServerPlugins" />
|
||||
<MakeDir Directories="$(PublishDir)ServerPlugins" />
|
||||
|
|
@ -50,6 +76,12 @@
|
|||
<Copy SourceFiles="@(ApiFiles)" DestinationFolder="$(OutDir)ServerPlugins" ContinueOnError="true" />
|
||||
<Copy SourceFiles="@(ApiFiles)" DestinationFolder="$(PublishDir)ServerPlugins" ContinueOnError="true" />
|
||||
</Target>
|
||||
<Target Name="CopyI18n" AfterTargets="Publish">
|
||||
<ItemGroup>
|
||||
<MOFiles Include="$(OutDir)**/*.mo"/>
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(MOFiles)" DestinationFolder="$(PublishDir)%(RecursiveDir)" />
|
||||
</Target>
|
||||
<Target Name="MoveBin" AfterTargets="Publish">
|
||||
<ItemGroup>
|
||||
<MoveBinaries Include="$(PublishDir)*" Exclude="$(PublishDir)\TShock.Server*" />
|
||||
|
|
|
|||
0
i18n/.gitkeep
Normal file
0
i18n/.gitkeep
Normal file
41
i18n/template.pot
Normal file
41
i18n/template.pot
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: TShock\n"
|
||||
"POT-Creation-Date: 2022-10-20 00:16:51-0400\n"
|
||||
"PO-Revision-Date: 2022-10-20 00:16:51-0400\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: GetText.NET Extractor\n"
|
||||
|
||||
#: ../../TShockAPI/Commands.cs:701
|
||||
#, csharp-format
|
||||
msgid "{0} executed: {1}{2}."
|
||||
msgstr ""
|
||||
|
||||
#: ../../TShockAPI/Commands.cs:687
|
||||
#, csharp-format
|
||||
msgid "{0} tried to execute {1}{2}."
|
||||
msgstr ""
|
||||
|
||||
#: ../../TShockAPI/Commands.cs:652
|
||||
#: ../../TShockAPI/Commands.cs:680
|
||||
#, csharp-format
|
||||
msgid "Invalid command entered. Type {0}help for a list of valid commands."
|
||||
msgstr ""
|
||||
|
||||
#: ../../TShockAPI/Commands.cs:691
|
||||
#, csharp-format
|
||||
msgid "You can use '{0}sudo {0}{1}' to override this check."
|
||||
msgstr ""
|
||||
|
||||
#: ../../TShockAPI/Commands.cs:688
|
||||
msgid "You do not have access to this command."
|
||||
msgstr ""
|
||||
|
||||
#: ../../TShockAPI/Commands.cs:696
|
||||
msgid "You must use this command in-game."
|
||||
msgstr ""
|
||||
|
||||
44
i18n/tok/TShockAPI.po
Normal file
44
i18n/tok/TShockAPI.po
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# Janet Blackquill <uhhadd@gmail.com>, 2022.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: TShock\n"
|
||||
"POT-Creation-Date: 2022-10-20 00:16:51-0400\n"
|
||||
"PO-Revision-Date: 2022-10-19 23:20-0400\n"
|
||||
"Last-Translator: Janet Blackquill <uhhadd@gmail.com>\n"
|
||||
"Language-Team: none>\n"
|
||||
"Language: tok\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=4; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || n%10>=5 && n%10<=9 || "
|
||||
"n%100>=11 && n%100<=14 ? 2 : 3;\n"
|
||||
"X-Generator: Lokalize 22.11.70\n"
|
||||
|
||||
#: ../../TShockAPI/Commands.cs:701
|
||||
#, csharp-format
|
||||
msgid "{0} executed: {1}{2}."
|
||||
msgstr "jan {0} li kepeken: {1}{2}."
|
||||
|
||||
#: ../../TShockAPI/Commands.cs:687
|
||||
#, csharp-format
|
||||
msgid "{0} tried to execute {1}{2}."
|
||||
msgstr "jan {0} li wile kepeken {1}{2}. taso ona li ken ala."
|
||||
|
||||
#: ../../TShockAPI/Commands.cs:652 ../../TShockAPI/Commands.cs:680
|
||||
#, csharp-format
|
||||
msgid "Invalid command entered. Type {0}help for a list of valid commands."
|
||||
msgstr "ilo ni li lon ala. sina wile sona e ilo lon la o toki e {0}help."
|
||||
|
||||
#: ../../TShockAPI/Commands.cs:691
|
||||
#, csharp-format
|
||||
msgid "You can use '{0}sudo {0}{1}' to override this check."
|
||||
msgstr "sina wile weka e awen pona ni la o kepeken '{0}sudo {0}{1}'."
|
||||
|
||||
#: ../../TShockAPI/Commands.cs:688
|
||||
msgid "You do not have access to this command."
|
||||
msgstr "sina ken ala kepeken ilo ni."
|
||||
|
||||
#: ../../TShockAPI/Commands.cs:696
|
||||
msgid "You must use this command in-game."
|
||||
msgstr "ilo ni li pali lon musi taso."
|
||||
Loading…
Add table
Add a link
Reference in a new issue