* Default AI content language to Ukrainian * Keep English as the default content language * refactor: update content language handling in workspace creation - Changed the default content language in CreateWorkspace to inherit the app's locale instead of defaulting to English. - Updated related tests to reflect this change, ensuring that the content language aligns with the application's current locale settings. - Cleaned up unnecessary code in the BrandTab component for better readability. * Add Ukrainian as a full platform UI locale. Wire uk into languages config with complete lang/uk translations and restore ContentLanguage↔UI parity checks. Co-authored-by: Cursor <cursoragent@cursor.com> * Wire Ukrainian into dayjs and locale coverage tests. Import the uk dayjs locale with Monday week-start and cover uk/uk-UA in brand autofill and SetLocale assertions. Co-authored-by: Cursor <cursoragent@cursor.com> * Harden Ukrainian UI and AI content-language coverage. Cover generator/reviewer/humanizer/image prompts, workspace pickers, persona labels, UI locale switch, and README for uk as a first-class platform language. Co-authored-by: Cursor <cursoragent@cursor.com> * Add Ukrainian Pinterest form strings after main merge. Restore lang/uk posts.php key parity for the new pin title and destination link fields. Co-authored-by: Cursor <cursoragent@cursor.com> * List every supported UI language in the README. Replace the abbreviated multi-language blurb with the full locale set from config. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Paulo Castellano <paulo@castellanos.llc> Co-authored-by: Cursor <cursoragent@cursor.com>
104 lines
4.2 KiB
PHP
104 lines
4.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Enums\Workspace\ContentLanguage;
|
|
|
|
test('values exposes every supported content-language code', function () {
|
|
expect(ContentLanguage::values())->toBe([
|
|
'en', 'uk', 'pt-BR', 'es', 'fr', 'de', 'it', 'nl',
|
|
'pl', 'el', 'ja', 'ko', 'zh', 'ru', 'tr', 'ar',
|
|
]);
|
|
});
|
|
|
|
test('default content language is English', function () {
|
|
expect(ContentLanguage::DEFAULT)->toBe(ContentLanguage::English);
|
|
expect(ContentLanguage::DEFAULT->value)->toBe('en');
|
|
});
|
|
|
|
test('options pairs each code with its native and English label', function () {
|
|
$options = ContentLanguage::options();
|
|
|
|
expect($options)->toHaveCount(count(ContentLanguage::cases()));
|
|
expect($options[0])->toBe(['value' => 'en', 'label' => 'English', 'englishName' => 'English']);
|
|
expect($options)->toContain(['value' => 'uk', 'label' => 'Українська', 'englishName' => 'Ukrainian']);
|
|
expect($options)->toContain(['value' => 'pt-BR', 'label' => 'Português (Brasil)', 'englishName' => 'Brazilian Portuguese']);
|
|
expect($options)->toContain(['value' => 'ja', 'label' => '日本語', 'englishName' => 'Japanese']);
|
|
});
|
|
|
|
test('englishName returns a distinct English name for every language', function (ContentLanguage $language, string $expected) {
|
|
expect($language->englishName())->toBe($expected);
|
|
})->with([
|
|
[ContentLanguage::English, 'English'],
|
|
[ContentLanguage::Ukrainian, 'Ukrainian'],
|
|
[ContentLanguage::PortugueseBrazil, 'Brazilian Portuguese'],
|
|
[ContentLanguage::Spanish, 'Spanish'],
|
|
[ContentLanguage::French, 'French'],
|
|
[ContentLanguage::German, 'German'],
|
|
[ContentLanguage::Italian, 'Italian'],
|
|
[ContentLanguage::Dutch, 'Dutch'],
|
|
[ContentLanguage::Polish, 'Polish'],
|
|
[ContentLanguage::Greek, 'Greek'],
|
|
[ContentLanguage::Japanese, 'Japanese'],
|
|
[ContentLanguage::Korean, 'Korean'],
|
|
[ContentLanguage::Chinese, 'Chinese'],
|
|
[ContentLanguage::Russian, 'Russian'],
|
|
[ContentLanguage::Turkish, 'Turkish'],
|
|
[ContentLanguage::Arabic, 'Arabic'],
|
|
]);
|
|
|
|
test('only English resolves to the English name', function () {
|
|
foreach (ContentLanguage::cases() as $language) {
|
|
expect($language->englishName() === 'English')->toBe($language === ContentLanguage::English);
|
|
}
|
|
});
|
|
|
|
test('label returns the native name for every language', function (ContentLanguage $language, string $expected) {
|
|
expect($language->label())->toBe($expected);
|
|
})->with([
|
|
[ContentLanguage::English, 'English'],
|
|
[ContentLanguage::Ukrainian, 'Українська'],
|
|
[ContentLanguage::PortugueseBrazil, 'Português (Brasil)'],
|
|
[ContentLanguage::Spanish, 'Español'],
|
|
[ContentLanguage::French, 'Français'],
|
|
[ContentLanguage::German, 'Deutsch'],
|
|
[ContentLanguage::Italian, 'Italiano'],
|
|
[ContentLanguage::Dutch, 'Nederlands'],
|
|
[ContentLanguage::Polish, 'Polski'],
|
|
[ContentLanguage::Greek, 'Ελληνικά'],
|
|
[ContentLanguage::Japanese, '日本語'],
|
|
[ContentLanguage::Korean, '한국어'],
|
|
[ContentLanguage::Chinese, '中文'],
|
|
[ContentLanguage::Russian, 'Русский'],
|
|
[ContentLanguage::Turkish, 'Türkçe'],
|
|
[ContentLanguage::Arabic, 'العربية'],
|
|
]);
|
|
|
|
test('direction is rtl only for Arabic', function () {
|
|
expect(ContentLanguage::Arabic->direction())->toBe('rtl');
|
|
|
|
foreach (ContentLanguage::cases() as $language) {
|
|
if ($language !== ContentLanguage::Arabic) {
|
|
expect($language->direction())->toBe('ltr');
|
|
}
|
|
}
|
|
});
|
|
|
|
test('fromHtmlLang resolves the two-letter primary subtag', function (string $lang, ?ContentLanguage $expected) {
|
|
expect(ContentLanguage::fromHtmlLang($lang))->toBe($expected);
|
|
})->with([
|
|
['pt', ContentLanguage::PortugueseBrazil],
|
|
['pt-PT', ContentLanguage::PortugueseBrazil],
|
|
['en-US', ContentLanguage::English],
|
|
['uk-UA', ContentLanguage::Ukrainian],
|
|
['es-MX', ContentLanguage::Spanish],
|
|
['fr', ContentLanguage::French],
|
|
['ja-JP', ContentLanguage::Japanese],
|
|
['zh-Hans', ContentLanguage::Chinese],
|
|
['sv', null],
|
|
['e', null],
|
|
['', null],
|
|
// A malformed tag is matched on its whole primary subtag, never a
|
|
// two-letter prefix — "english" must not resolve to English via "en".
|
|
['english', null],
|
|
]);
|