Skip to content

Commit e9e34f7

Browse files
committed
Add new translate action: move, make i18n-move-key (FreshRSS#8214)
So that renaming something like `conf.shortcut.toggle_sidebar` to `conf.shortcut.toggle_aside` can be done easily even after already having added `conf.shortcut.toggle_sidebar` and translated it in multiple languages. Example of usage: ```console ./cli/manipulate.translation.php -a move -k conf.shortcut.toggle_sidebar -n conf.shortcut.toggle_aside ``` ```console make i18n-move-key key="conf.shortcut.toggle_sidebar" new-key="conf.shortcut.toggle_aside" ``` The key will be moved and all values/states will be kept.
1 parent 209f10a commit e9e34f7

File tree

5 files changed

+69
-7
lines changed

5 files changed

+69
-7
lines changed

Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,17 @@ endif
114114
@$(PHP) ./cli/manipulate.translation.php --action add --key $(key) --value "$(value)"
115115
@echo Key added.
116116

117+
.PHONY: i18n-move-key
118+
i18n-move-key: ## Move an existing key into a new location
119+
ifndef key
120+
$(error To move a key, you need to provide one in the "key" variable)
121+
endif
122+
ifndef new-key
123+
$(error To specify a location to move the key to, you need to provide it in the "new-key" variable)
124+
endif
125+
@$(PHP) ./cli/manipulate.translation.php --action move --key $(key) --new-key "$(new-key)"
126+
@echo Key moved.
127+
117128
.PHONY: i18n-add-language
118129
i18n-add-language: ## Add a new supported language
119130
ifndef lang

cli/i18n/I18nData.php

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ private function getNonReferenceLanguages(): array {
9898
*/
9999
public function addLanguage(string $language, ?string $reference = null): void {
100100
if (array_key_exists($language, $this->data)) {
101-
throw new Exception('The selected language already exist.');
101+
throw new Exception('The selected language already exists.');
102102
}
103103
if (!is_string($reference) || !array_key_exists($reference, $this->data)) {
104104
$reference = static::REFERENCE_LANGUAGE;
@@ -221,7 +221,7 @@ public function addKey(string $key, string $value): void {
221221
}
222222

223223
if ($this->isKnown($key)) {
224-
throw new Exception('The selected key already exist.');
224+
throw new Exception('The selected key already exists.');
225225
}
226226

227227
$parentKey = $this->getParentKey($key);
@@ -248,6 +248,29 @@ public function addKey(string $key, string $value): void {
248248
}
249249
}
250250

251+
/**
252+
* Move an existing key into a new location
253+
* @throws Exception
254+
*/
255+
public function moveKey(string $key, string $newKey): void {
256+
if (!$this->isKnown($key) && !$this->isKnown($this->getEmptySibling($key))) {
257+
throw new Exception('The selected key does not exist');
258+
}
259+
if ($this->isKnown($newKey)) {
260+
throw new Exception('Cannot move key to a location that already exists.');
261+
}
262+
263+
$keyPrefix = $this->isParent($key) ? $key . '.' : $key;
264+
foreach ($this->getAvailableLanguages() as $language) {
265+
foreach ($this->data[$language][$this->getFilenamePrefix($key)] as $k => $v) {
266+
if (str_starts_with($k, $keyPrefix)) {
267+
$this->data[$language][$this->getFilenamePrefix($newKey)][str_replace($key, $newKey, $k)] = $v;
268+
unset($this->data[$language][$this->getFilenamePrefix($key)][$k]);
269+
}
270+
}
271+
}
272+
}
273+
251274
/**
252275
* Add a value for a key for the selected language.
253276
*

cli/manipulate.translation.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
$cliOptions = new class extends CliOptionsParser {
1010
public string $action;
1111
public string $key;
12+
public string $newKey;
1213
public string $value;
1314
public string $language;
1415
public string $originLanguage;
@@ -18,6 +19,7 @@
1819
public function __construct() {
1920
$this->addRequiredOption('action', (new CliOption('action', 'a')));
2021
$this->addOption('key', (new CliOption('key', 'k')));
22+
$this->addOption('newKey', (new CliOption('new-key', 'n')));
2123
$this->addOption('value', (new CliOption('value', 'v')));
2224
$this->addOption('language', (new CliOption('language', 'l')));
2325
$this->addOption('originLanguage', (new CliOption('origin-language', 'o')));
@@ -56,6 +58,14 @@ public function __construct() {
5658
exit;
5759
}
5860
break;
61+
case 'move':
62+
if (isset($cliOptions->key) && isset($cliOptions->newKey)) {
63+
$i18nData->moveKey($cliOptions->key, $cliOptions->newKey);
64+
} else {
65+
error('You need to specify the key to move and its new location.');
66+
exit;
67+
}
68+
break;
5969
case 'delete':
6070
if (isset($cliOptions->key)) {
6171
$i18nData->removeKey($cliOptions->key);
@@ -131,7 +141,7 @@ function manipulateHelp(): void {
131141
Manipulate translation files.
132142
133143
-a, --action=ACTION
134-
select the action to perform. Available actions are add, delete,
144+
select the action to perform. Available actions are add, move, delete,
135145
exist, format, ignore, and ignore_unmodified. This option is mandatory.
136146
-k, --key=KEY select the key to work on.
137147
-v, --value=VAL select the value to set.
@@ -176,6 +186,9 @@ function manipulateHelp(): void {
176186
177187
Example 11: add a new file to all languages
178188
php $file -a add -k my_file.php
179-
HELP;
189+
190+
Example 12:\tmove an existing key into a new location
191+
php $file -a move -k my_key -n new_location
192+
HELP, PHP_EOL;
180193
exit();
181194
}

docs/en/internationalization.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ make i18n-ignore-key lang=fr key=index.about.version
8383

8484
This command adds an IGNORE comment on the translation so the key can be considered as translated.
8585

86-
## Add/remove/update a key
86+
## Add/remove/update/rename a key
8787

8888
If you’re developing a new part of the application, you might want to declare a new translation key. Your first impulse would be to add the key to each file manually: don’t do that, it’s very painful. We provide another command:
8989

@@ -107,6 +107,11 @@ make i18n-update-key key=the.key.to.change value='The new string in English'
107107

108108
The key will simply be removed and added back with the new value.
109109

110+
If you want to move/rename a key, you can use:
111+
```sh
112+
make i18n-move-key key=the.key.to.move new-key=new.location.of.the.key
113+
```
114+
110115
## How to access a translation programmatically
111116

112117
To access these translations, you must use the `_t()` function (which is a shortcut for `Minz_Translate::t()`). Code example:

tests/cli/i18n/I18nDataTest.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ public function setUp(): void {
3434
];
3535
}
3636

37+
public function testMoveKey(): void {
38+
$data = new I18nData($this->referenceData);
39+
$value = $data->getData()['en']['file2.php']['file2.l1.l2.k2'];
40+
self::assertTrue($data->isKnown('file2.l1.l2.k2'));
41+
self::assertFalse($data->isKnown('file2.l1.nkl2'));
42+
$data->moveKey('file2.l1.l2.k2', 'file2.l1.nkl2');
43+
self::assertFalse($data->isKnown('file2.l1.l2.k2'));
44+
self::assertTrue($data->isKnown('file2.l1.nkl2'));
45+
}
46+
3747
public function testConstructWhenReferenceOnly(): void {
3848
$data = new I18nData($this->referenceData);
3949
self::assertSame($this->referenceData, $data->getData());
@@ -302,7 +312,7 @@ public function testGetAvailableLanguagesWhenTheyAreNotSorted(): void {
302312

303313
public function testAddLanguageWhenLanguageExists(): void {
304314
$this->expectException(\Exception::class);
305-
$this->expectExceptionMessage('The selected language already exist.');
315+
$this->expectExceptionMessage('The selected language already exists.');
306316
$data = new I18nData($this->referenceData);
307317
$data->addLanguage('en');
308318
}
@@ -430,7 +440,7 @@ public function testIsKnownWhenKeyDoesNotExist(): void {
430440

431441
public function testAddKeyWhenKeyExists(): void {
432442
$this->expectException(\Exception::class);
433-
$this->expectExceptionMessage('The selected key already exist.');
443+
$this->expectExceptionMessage('The selected key already exists.');
434444
$data = new I18nData($this->referenceData);
435445
$data->addKey('file2.l1.l2.k1', 'value');
436446
}

0 commit comments

Comments
 (0)