Merge the Language repo into the main PM repo

the separated language repository has long been a source of inconvenience and annoyance,
particularly for PR contributors, because having to sync two PRs across different repos
for no reason adds unnecessary friction.

In addition, having the language files separate creates unnecessary requirements for
versioning and branching, which could all be avoided if the language strings were managed
directly in this repository.

This change will make it much easier to do new features that require adding new translation
strings, as well as getting rid of the inconvenience of cleaning up older strings.
Translation updates from Crowdin should also be able to be merged more quickly, since they
will have higher visibility on this repository.
This commit is contained in:
Dylan K. Taylor
2025-10-18 15:12:22 +01:00
parent 25e1feadd8
commit 87afd545fd
20 changed files with 190 additions and 134 deletions

3
.gitattributes vendored
View File

@@ -9,6 +9,9 @@
*.cmd text eol=crlf
*.ps1 text eol=crlf
# Not sure why these use CRLF, but keeping consistent with the old repository for now
/resources/translations/*.ini text eol=crlf
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union

View File

@@ -7,12 +7,6 @@ updates:
time: "10:00"
open-pull-requests-limit: 10
ignore:
#only allow patch updates for locale-data - this has to be updated manually due to codegen
- dependency-name: pocketmine/locale-data
update-types:
- "version-update:semver-major"
- "version-update:semver-minor"
#since we lock this to exact versions, it causes conflicts with minor-next & major-next in composer.lock
#better to just test updates to this locally anyway since almost every version breaks something
- dependency-name: phpstan/phpstan

View File

@@ -4,7 +4,6 @@ on:
schedule:
- cron: 0 21 * * * #every day at 9pm
workflow_dispatch:
push:
jobs:
download:
@@ -13,7 +12,11 @@ jobs:
strategy:
matrix:
branch: [ stable ]
branch:
- stable
- minor-next
- major-next
fail-fast: false
steps:
- uses: actions/checkout@v4
@@ -35,12 +38,14 @@ jobs:
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
- name: Post-process placeholders back into PocketMine format
working-directory: resources/translations
run: |
sed -i -r 's/\{([A-Za-z0-9]+)\}/\{%\1\}/g' *.ini
git diff
git status
- name: Delete translation files with no translations
working-directory: resources/translations
run: |
for file in *.ini; do
if grep -q -P '^[A-Za-z0-9_\-\.]+=' $file; then
@@ -55,7 +60,7 @@ jobs:
uses: peter-evans/create-pull-request@v7
with:
add-paths: '*.ini'
commit-message: 'New translations from Crowdin'
commit-message: 'New translations from Crowdin (${{ matrix.branch }})'
branch: crowdin-auto-fetch/${{ matrix.branch }}
title: 'New translations from Crowdin'
base: ${{ matrix.branch }}

View File

@@ -3,7 +3,11 @@ name: Upload translations to Crowdin
on:
push:
paths:
- eng.ini
- resources/translations/eng.ini
branches:
- stable
- minor-next
- major-next
workflow_dispatch:
jobs:
@@ -15,6 +19,7 @@ jobs:
- uses: actions/checkout@v5
- name: Preprocess eng.ini placeholders so Crowdin can understand them
working-directory: resources/translations
run: |
sed -i -r 's/\{%([A-Za-z0-9]+)\}/\{\1\}/g' eng.ini
cat eng.ini

View File

@@ -29,6 +29,7 @@ use function explode;
use function file_get_contents;
use function fwrite;
use function in_array;
use function is_array;
use function json_decode;
use function json_encode;
use function parse_ini_file;
@@ -38,6 +39,7 @@ use const INI_SCANNER_RAW;
use const JSON_PRETTY_PRINT;
use const JSON_THROW_ON_ERROR;
use const PHP_EOL;
use const PHP_INT_MAX;
use const STDERR;
/**
@@ -85,6 +87,10 @@ function verify_translations(array $baseLanguageDef, string $altLanguageName, ar
return $ok;
}
/**
* @return string[]|null
* @phpstan-return array<string, string>|null
*/
function parse_language_file(string $path, string $code) : ?array{
$lang = parse_ini_file($path . "/" . "$code.ini", false, INI_SCANNER_RAW);
if($lang === false){
@@ -93,9 +99,13 @@ function parse_language_file(string $path, string $code) : ?array{
return $lang;
}
/**
* @return string[]
* @phpstan-return array<string, string>
*/
function parse_mojang_language_defs(string $contents) : array{
$result = [];
foreach(explode("\n", $contents) as $line){
foreach(explode("\n", $contents, limit: PHP_INT_MAX) as $line){
$stripped = explode("##", $line, 2)[0];
$kv = explode("=", $stripped, 2);
if(count($kv) !== 2){
@@ -107,6 +117,17 @@ function parse_mojang_language_defs(string $contents) : array{
return $result;
}
/**
* @param string[] $pocketmine
* @param string[] $mojang
* @param string[] $knownBadKeys
* @phpstan-param array<string, string> $pocketmine
* @phpstan-param array<string, string> $mojang
* @phpstan-param array<string, bool> $knownBadKeys
*
* @return string[]
* @phpstan-return list<string>
*/
function verify_keys(array $pocketmine, array $mojang, array $knownBadKeys) : array{
$wrong = [];
foreach($pocketmine as $k => $v){
@@ -138,8 +159,21 @@ if($mojangRaw === false){
}
$mojang = parse_mojang_language_defs($mojangRaw);
$knownBadKeysRaw = file_get_contents(__DIR__ . "/known-bad-keys.json");
$knownBadKeys = $knownBadKeysRaw !== false ? json_decode($knownBadKeysRaw, associative: true, flags: JSON_THROW_ON_ERROR) : [];
$knownBadKeysRaw = file_get_contents($argv[1] . "/known-bad-keys.json");
$knownBadKeysDecoded = $knownBadKeysRaw !== false ? json_decode($knownBadKeysRaw, associative: true, flags: JSON_THROW_ON_ERROR) : [];
if(!is_array($knownBadKeysDecoded)){
fwrite(STDERR, "known-bad-keys.json should contain an array of strings\n");
exit(1);
}
$knownBadKeys = [];
foreach($knownBadKeysDecoded as $key){
if(!is_string($key)){
fwrite(STDERR, "known-bad-keys.json should contain an array of strings\n");
exit(1);
}
$knownBadKeys[] = $key;
}
$badKeys = verify_keys($eng, $mojang, array_fill_keys($knownBadKeys, true));
if(count($badKeys) !== 0){
@@ -151,6 +185,10 @@ if(count($badKeys) !== 0){
}
$exit = 0;
/**
* @var string[] $match
* @phpstan-var array{0: string, 1: string} $match
*/
foreach(new \RegexIterator(new \FilesystemIterator($argv[1], \FilesystemIterator::CURRENT_AS_PATHNAME), "/([a-z]+)\.ini$/", \RegexIterator::GET_MATCH) as $match){
$code = $match[1];
if($code === "eng"){

View File

@@ -3,7 +3,7 @@ name: Verify translations
on:
push:
branches-ignore:
- 'l10n/*'
- 'crowdin-auto-fetch/*' #this will be run on pull_request anyway
pull_request:
workflow_dispatch:
@@ -20,4 +20,4 @@ jobs:
php-version: 8.3
- name: Verify translations
run: php .github/workflows/verify-translations.php ${{ github.workspace }}
run: php .github/workflows/verify-translations.php ${{ github.workspace }}/resources/translations

View File

@@ -4,6 +4,12 @@ Small contributions (e.g. minor bug fixes) can be submitted as pull requests dir
Larger contributions like feature additions should be preceded by a [Change Proposal](#rfcs--change-proposals) to allow maintainers and other people to discuss and decide if it's a good idea or not.
> [!TIP]
> Want to contribute (non-English) translations? Visit our
> [Crowdin Translation Project](https://crowdin.com/project/pocketmine) instead.
>
> Translations need to go through a different review process, so we can't accept changes to them in PRs.
## Useful documentation from github.com
- [About pull requests](https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests)
- [About forks](https://docs.github.com/en/github/collaborating-with-pull-requests/working-with-forks/about-forks)
@@ -37,22 +43,24 @@ Take a look at the table below if you can't find the class or function you're lo
## Choosing a target branch
PocketMine-MP has three primary branches of development.
| Type of change | `stable` | `minor-next` | `major-next` |
|:--------------------------------------------------------------------------------------------|:--------:|:-------------------------------:|:------------:|
| Bug fixes | ✔️ | ✔️ | ✔️ |
| Improvements to API docs | ✔️ | ✔️ | ✔️ |
| Cleaning up code | | ✔️ | ✔️ |
| Changing code formatting or style | ❌ | ✔️ | ✔️ |
| Addition of new core features | ❌ | 🟡 Only if non-disruptive | ✔️ |
| Changing core behaviour (e.g. making something use threads) | ❌ | ✔️ | ✔️ |
| Addition of new configuration options | ❌ | 🟡 Only if optional | ✔️ |
| Addition of new API classes, methods or constants | ❌ | ✔️ | ✔️ |
| Deprecating API classes, methods or constants | ❌ | ✔️ | ✔️ |
| Adding optional parameters to an API method | ❌ | ✔️ | ✔️ |
| Changing API behaviour | ❌ | 🟡 Only if backwards-compatible | ✔️ |
| Removal of API | ❌ | | ✔️ |
| Backwards-incompatible API change (e.g. renaming a method) | ❌ | | ✔️ |
| Backwards-incompatible internals change (e.g. changing things in `pocketmine\network\mcpe`) | ❌ | ✔️ | ✔️ |
| Type of change | `stable` | `minor-next` | `major-next` |
|:---------------------------------------------------------------------------------------------------------|:--------:|:-------------------------------:|:------------:|
| Bug fixes | ✔️ | ✔️ | ✔️ |
| Improvements to API docs | ✔️ | ✔️ | ✔️ |
| Fixing base (`eng.ini`) language strings, or adding new ones | ✔️ | ✔️ | ✔️ |
| Changes to existing base (`eng.ini`) language strings (e.g. changing parameters, renaming/removing keys) | ❌ | ✔️ | ✔️ |
| Cleaning up code | ❌ | ✔️ | ✔️ |
| Changing code formatting or style | ❌ | ✔️ | ✔️ |
| Addition of new core features | ❌ | 🟡 Only if non-disruptive | ✔️ |
| Changing core behaviour (e.g. making something use threads) | ❌ | ✔️ | ✔️ |
| Addition of new configuration options | ❌ | 🟡 Only if optional | ✔️ |
| Addition of new API classes, methods or constants | ❌ | ✔️ | ✔️ |
| Deprecating API classes, methods or constants | ❌ | ✔️ | ✔️ |
| Adding optional parameters to an API method | ❌ | ✔️ | ✔️ |
| Changing API behaviour | ❌ | 🟡 Only if backwards-compatible | ✔️ |
| Removal of API | ❌ | | ✔️ |
| Backwards-incompatible API change (e.g. renaming a method) | ❌ | ❌ | ✔️ |
| Backwards-incompatible internals change (e.g. changing things in `pocketmine\network\mcpe`) | ❌ | ✔️ | ✔️ |
### Notes
- **Non-disruptive** means that usage should not be significantly altered by the change.

View File

@@ -42,7 +42,6 @@
"pocketmine/callback-validator": "^1.0.2",
"pocketmine/color": "^0.3.0",
"pocketmine/errorhandler": "^0.7.0",
"pocketmine/locale-data": "~2.26.0",
"pocketmine/log": "^0.4.0",
"pocketmine/math": "~1.0.0",
"pocketmine/nbt": "~1.2.0",

25
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "ad9a8e8069598ae5ec679f069461623f",
"content-hash": "2c893fe1da8c1159aec2f54de70c1119",
"packages": [
{
"name": "adhocore/json-comment",
@@ -470,29 +470,6 @@
},
"time": "2024-04-02T18:29:54+00:00"
},
{
"name": "pocketmine/locale-data",
"version": "2.26.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/Language.git",
"reference": "f791369ae082fc5cdf0f2b0bd683e611ff7f90f6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/Language/zipball/f791369ae082fc5cdf0f2b0bd683e611ff7f90f6",
"reference": "f791369ae082fc5cdf0f2b0bd683e611ff7f90f6",
"shasum": ""
},
"type": "library",
"notification-url": "https://packagist.org/downloads/",
"description": "Language resources used by PocketMine-MP",
"support": {
"issues": "https://github.com/pmmp/Language/issues",
"source": "https://github.com/pmmp/Language/tree/2.26.0"
},
"time": "2025-10-07T17:26:32+00:00"
},
{
"name": "pocketmine/log",
"version": "0.4.0",

7
crowdin.yml Normal file
View File

@@ -0,0 +1,7 @@
files:
- source: resources/translations/eng.ini
translation: /resources/translations/%three_letters_code%.ini
languages_mapping:
three_letters_code:
zh-CN: chs
pt-BR: bra

View File

@@ -1,4 +0,0 @@
<!--
Please note that translation contributions should be done on http://translate.pocketmine.net,
not with a pull request. Pull requests with translations will be closed.
-->

View File

@@ -1,6 +0,0 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: monthly

View File

@@ -1,47 +0,0 @@
name: Tag new patch releases on branch push
on:
push:
branches: [ stable ]
workflow_dispatch:
jobs:
build:
name: Tag new patch release
runs-on: ubuntu-latest
if: "github.event_name == 'workflow_dispatch' || startsWith(github.event.head_commit.message, 'New translations') || startsWith(github.event.head_commit.message, 'New Crowdin updates') "
concurrency: tag-patches
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 #we need to fetch tags to calculate new patch number
- name: Tag new version
run: |
BASE_VERSION="2.27"
PREVIOUS_TAG=$(git tag --list | awk -v s="$BASE_VERSION." 'index($0, s) == 1' | sort -r --version-sort | head -n1)
echo "Previous tag is $PREVIOUS_TAG"
PREVIOUS_PATCH=$(echo "$PREVIOUS_TAG" | cut -d. -f3)
regex='^[0-9]+$'
if [[ "$PREVIOUS_PATCH" =~ ^[0-9]+$ ]]; then
PATCH_VERSION="$(($PREVIOUS_PATCH+1))"
elif [[ "$PREVIOUS_PATCH" == "" ]]; then
PATCH_VERSION="0"
else
echo "Can't calculate next patch number from tag $PREVIOUS_TAG"
exit 1
fi
FULL_VERSION="$BASE_VERSION.$PATCH_VERSION"
echo "Tagging version $FULL_VERSION"
git config user.name github-actions
git config user.email github-actions@github.com
git tag "$FULL_VERSION"
- name: Push changes
run: git push origin --tags

View File

@@ -3,17 +3,11 @@
These files contain translation strings used in PocketMine-MP.
## Contributing translations
To contribute translations, please use the [Crowdin Translation Page](http://translate.pocketmine.net/), select the language you want to translate and and go to PocketMine-MP and select "PocketMine core strings". There may be multiple branches available - if in doubt, stick with `stable`.
To contribute translations, please use the [Crowdin Translation Page](http://translate.pocketmine.net/), select the language you want to translate and go to PocketMine-MP and select "PocketMine core strings". There may be multiple branches available - if in doubt, stick with `stable`.
## For maintainers
### Adding new strings
Only English should be modified directly. To add new strings, add them ONLY to eng.ini. Crowdin will then synchronize them and the new strings will be put up for translation within Crowdin.
### Versioning
- Versions must be updated in [`tag-patches.yml` workflow](.github/workflows/tag-patches.yml#L19).
- When removing a string, or adding/removing/renaming parameters, bump the major version, e.g. `2.8.0` -> `3.0.0`
- When adding new strings, bump the minor version, e.g. `2.8.0` -> `2.9.0`
- Patches are automatically tagged by GitHub Actions whenever new translations are merged from Crowdin.
### Pitfalls
- If you have issues with translation files being deleted, add a language mapping in the Crowdin config. Some issues arose with Chinese due to Chinese Simplified and Chinese Traditional both mapping to `zho`, requiring a mapping to `zho-cn` for simplified.

View File

@@ -1,6 +0,0 @@
{
"name": "pocketmine/locale-data",
"description": "Language resources used by PocketMine-MP",
"type": "library",
"require": {}
}

View File

@@ -1,7 +0,0 @@
files:
- source: eng.ini
translation: /%three_letters_code%.ini
languages_mapping:
three_letters_code:
zh-CN: chs
pt-BR: bra

View File

@@ -36,7 +36,7 @@ define('pocketmine\_CORE_CONSTANTS_INCLUDED', true);
define('pocketmine\PATH', dirname(__DIR__) . '/');
define('pocketmine\RESOURCE_PATH', dirname(__DIR__) . '/resources/');
define('pocketmine\BEDROCK_DATA_PATH', dirname(__DIR__) . '/vendor/pocketmine/bedrock-data/');
define('pocketmine\LOCALE_DATA_PATH', dirname(__DIR__) . '/vendor/pocketmine/locale-data/');
define('pocketmine\LOCALE_DATA_PATH', dirname(__DIR__) . '/resources/translations/');
define('pocketmine\BEDROCK_BLOCK_UPGRADE_SCHEMA_PATH', dirname(__DIR__) . '/vendor/pocketmine/bedrock-block-upgrade-schema/');
define('pocketmine\BEDROCK_ITEM_UPGRADE_SCHEMA_PATH', dirname(__DIR__) . '/vendor/pocketmine/bedrock-item-upgrade-schema/');
define('pocketmine\COMPOSER_AUTOLOADER_PATH', dirname(__DIR__) . '/vendor/autoload.php');

View File

@@ -1535,6 +1535,62 @@ final class KnownTranslationFactory{
return new Translatable(KnownTranslationKeys::POCKETMINE_COMMAND_CLEAR_USAGE, []);
}
public static function pocketmine_command_cmdalias_create_success(Translatable|string $alias, Translatable|string $target) : Translatable{
return new Translatable(KnownTranslationKeys::POCKETMINE_COMMAND_CMDALIAS_CREATE_SUCCESS, [
"alias" => $alias,
"target" => $target,
]);
}
public static function pocketmine_command_cmdalias_delete_notFound(Translatable|string $alias) : Translatable{
return new Translatable(KnownTranslationKeys::POCKETMINE_COMMAND_CMDALIAS_DELETE_NOTFOUND, [
"alias" => $alias,
]);
}
public static function pocketmine_command_cmdalias_delete_success(Translatable|string $alias) : Translatable{
return new Translatable(KnownTranslationKeys::POCKETMINE_COMMAND_CMDALIAS_DELETE_SUCCESS, [
"alias" => $alias,
]);
}
public static function pocketmine_command_cmdalias_description() : Translatable{
return new Translatable(KnownTranslationKeys::POCKETMINE_COMMAND_CMDALIAS_DESCRIPTION, []);
}
public static function pocketmine_command_cmdalias_list_conflicted(Translatable|string $alias, Translatable|string $commandIds) : Translatable{
return new Translatable(KnownTranslationKeys::POCKETMINE_COMMAND_CMDALIAS_LIST_CONFLICTED, [
"alias" => $alias,
"commandIds" => $commandIds,
]);
}
public static function pocketmine_command_cmdalias_list_noneSet() : Translatable{
return new Translatable(KnownTranslationKeys::POCKETMINE_COMMAND_CMDALIAS_LIST_NONESET, []);
}
public static function pocketmine_command_cmdalias_list_normal(Translatable|string $alias, Translatable|string $commandId) : Translatable{
return new Translatable(KnownTranslationKeys::POCKETMINE_COMMAND_CMDALIAS_LIST_NORMAL, [
"alias" => $alias,
"commandId" => $commandId,
]);
}
public static function pocketmine_command_cmdalias_scope_global() : Translatable{
return new Translatable(KnownTranslationKeys::POCKETMINE_COMMAND_CMDALIAS_SCOPE_GLOBAL, []);
}
public static function pocketmine_command_cmdalias_scope_userSpecific() : Translatable{
return new Translatable(KnownTranslationKeys::POCKETMINE_COMMAND_CMDALIAS_SCOPE_USERSPECIFIC, []);
}
public static function pocketmine_command_cmdalias_template(Translatable|string $message, Translatable|string $scope) : Translatable{
return new Translatable(KnownTranslationKeys::POCKETMINE_COMMAND_CMDALIAS_TEMPLATE, [
"message" => $message,
"scope" => $scope,
]);
}
public static function pocketmine_command_defaultgamemode_description() : Translatable{
return new Translatable(KnownTranslationKeys::POCKETMINE_COMMAND_DEFAULTGAMEMODE_DESCRIPTION, []);
}
@@ -1559,6 +1615,19 @@ final class KnownTranslationFactory{
return new Translatable(KnownTranslationKeys::POCKETMINE_COMMAND_ENCHANT_DESCRIPTION, []);
}
public static function pocketmine_command_error_aliasConflict(Translatable|string $alias, Translatable|string $commandIdList) : Translatable{
return new Translatable(KnownTranslationKeys::POCKETMINE_COMMAND_ERROR_ALIASCONFLICT, [
"alias" => $alias,
"commandIdList" => $commandIdList,
]);
}
public static function pocketmine_command_error_aliasConflictTip(Translatable|string $cmdAliasCommand) : Translatable{
return new Translatable(KnownTranslationKeys::POCKETMINE_COMMAND_ERROR_ALIASCONFLICTTIP, [
"cmdAliasCommand" => $cmdAliasCommand,
]);
}
public static function pocketmine_command_error_permission(Translatable|string $commandName) : Translatable{
return new Translatable(KnownTranslationKeys::POCKETMINE_COMMAND_ERROR_PERMISSION, [
"commandName" => $commandName,
@@ -2227,6 +2296,18 @@ final class KnownTranslationFactory{
return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_CLEAR_SELF, []);
}
public static function pocketmine_permission_command_cmdalias_edit_global() : Translatable{
return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_CMDALIAS_EDIT_GLOBAL, []);
}
public static function pocketmine_permission_command_cmdalias_edit_self() : Translatable{
return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_CMDALIAS_EDIT_SELF, []);
}
public static function pocketmine_permission_command_cmdalias_list() : Translatable{
return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_CMDALIAS_LIST, []);
}
public static function pocketmine_permission_command_defaultgamemode() : Translatable{
return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_DEFAULTGAMEMODE, []);
}

View File

@@ -347,12 +347,24 @@ final class KnownTranslationKeys{
public const POCKETMINE_COMMAND_BANLIST_DESCRIPTION = "pocketmine.command.banlist.description";
public const POCKETMINE_COMMAND_CLEAR_DESCRIPTION = "pocketmine.command.clear.description";
public const POCKETMINE_COMMAND_CLEAR_USAGE = "pocketmine.command.clear.usage";
public const POCKETMINE_COMMAND_CMDALIAS_CREATE_SUCCESS = "pocketmine.command.cmdalias.create.success";
public const POCKETMINE_COMMAND_CMDALIAS_DELETE_NOTFOUND = "pocketmine.command.cmdalias.delete.notFound";
public const POCKETMINE_COMMAND_CMDALIAS_DELETE_SUCCESS = "pocketmine.command.cmdalias.delete.success";
public const POCKETMINE_COMMAND_CMDALIAS_DESCRIPTION = "pocketmine.command.cmdalias.description";
public const POCKETMINE_COMMAND_CMDALIAS_LIST_CONFLICTED = "pocketmine.command.cmdalias.list.conflicted";
public const POCKETMINE_COMMAND_CMDALIAS_LIST_NONESET = "pocketmine.command.cmdalias.list.noneSet";
public const POCKETMINE_COMMAND_CMDALIAS_LIST_NORMAL = "pocketmine.command.cmdalias.list.normal";
public const POCKETMINE_COMMAND_CMDALIAS_SCOPE_GLOBAL = "pocketmine.command.cmdalias.scope.global";
public const POCKETMINE_COMMAND_CMDALIAS_SCOPE_USERSPECIFIC = "pocketmine.command.cmdalias.scope.userSpecific";
public const POCKETMINE_COMMAND_CMDALIAS_TEMPLATE = "pocketmine.command.cmdalias.template";
public const POCKETMINE_COMMAND_DEFAULTGAMEMODE_DESCRIPTION = "pocketmine.command.defaultgamemode.description";
public const POCKETMINE_COMMAND_DEOP_DESCRIPTION = "pocketmine.command.deop.description";
public const POCKETMINE_COMMAND_DIFFICULTY_DESCRIPTION = "pocketmine.command.difficulty.description";
public const POCKETMINE_COMMAND_DUMPMEMORY_DESCRIPTION = "pocketmine.command.dumpmemory.description";
public const POCKETMINE_COMMAND_EFFECT_DESCRIPTION = "pocketmine.command.effect.description";
public const POCKETMINE_COMMAND_ENCHANT_DESCRIPTION = "pocketmine.command.enchant.description";
public const POCKETMINE_COMMAND_ERROR_ALIASCONFLICT = "pocketmine.command.error.aliasConflict";
public const POCKETMINE_COMMAND_ERROR_ALIASCONFLICTTIP = "pocketmine.command.error.aliasConflictTip";
public const POCKETMINE_COMMAND_ERROR_PERMISSION = "pocketmine.command.error.permission";
public const POCKETMINE_COMMAND_ERROR_PLAYERNOTFOUND = "pocketmine.command.error.playerNotFound";
public const POCKETMINE_COMMAND_EXCEPTION = "pocketmine.command.exception";
@@ -489,6 +501,9 @@ final class KnownTranslationKeys{
public const POCKETMINE_PERMISSION_COMMAND_BAN_PLAYER = "pocketmine.permission.command.ban.player";
public const POCKETMINE_PERMISSION_COMMAND_CLEAR_OTHER = "pocketmine.permission.command.clear.other";
public const POCKETMINE_PERMISSION_COMMAND_CLEAR_SELF = "pocketmine.permission.command.clear.self";
public const POCKETMINE_PERMISSION_COMMAND_CMDALIAS_EDIT_GLOBAL = "pocketmine.permission.command.cmdalias.edit.global";
public const POCKETMINE_PERMISSION_COMMAND_CMDALIAS_EDIT_SELF = "pocketmine.permission.command.cmdalias.edit.self";
public const POCKETMINE_PERMISSION_COMMAND_CMDALIAS_LIST = "pocketmine.permission.command.cmdalias.list";
public const POCKETMINE_PERMISSION_COMMAND_DEFAULTGAMEMODE = "pocketmine.permission.command.defaultgamemode";
public const POCKETMINE_PERMISSION_COMMAND_DIFFICULTY = "pocketmine.permission.command.difficulty";
public const POCKETMINE_PERMISSION_COMMAND_DUMPMEMORY = "pocketmine.permission.command.dumpmemory";