1<?php
2
3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
4// See the LICENCE file in the repository root for full licence text.
5
6namespace Tests;
7
8use App;
9use App\Models\User;
10
11class LocaleTest extends TestCase
12{
13 public function testAll()
14 {
15 $fallbackLocale = 'en';
16 osu_trans()->addLines([
17 'key_1.simple' => 'test',
18 'key_1.simple_empty' => 'test 2',
19 'key_1.simple_missing' => 'test 3',
20 'key_1.keyed' => 'test: :value',
21 'key_1.keyed_empty' => 'test 2: :value',
22 'key_1.keyed_missing' => 'test 3: :value',
23 'key_1.choice' => ':count unit|:count units',
24 'key_1.choice_empty' => ':count item|:count items',
25 'key_1.choice_missing' => ':count entity|:count entities',
26 'key_1.empty' => '',
27 'key_1.empty_empty' => '',
28 'key_1.empty_missing' => '',
29 ], $fallbackLocale);
30
31 app()->setLocale($fallbackLocale);
32 $this->assertSame('key_1.missing', osu_trans('key_1.missing'));
33 $this->assertSame('test', osu_trans('key_1.simple'));
34 $this->assertSame('test: stuff', osu_trans('key_1.keyed', ['value' => 'stuff']));
35 $this->assertSame('1 unit', osu_trans_choice('key_1.choice', 1));
36 $this->assertSame('2 units', osu_trans_choice('key_1.choice', 2));
37 $this->assertSame('', osu_trans('key_1.empty'));
38
39 $incompleteLocale = 'ja';
40 osu_trans()->addLines([
41 'key_1.simple' => 'テスト',
42 'key_1.simple_empty' => '',
43 'key_1.keyed' => 'テスト: :value',
44 'key_1.keyed_empty' => '',
45 'key_1.choice' => ':count個',
46 'key_1.choice_empty' => '',
47 'key_1.empty' => '',
48 ], $incompleteLocale);
49
50 app('translator')->setFallback($fallbackLocale);
51 app()->setLocale($incompleteLocale);
52 $this->assertSame('key_1.missing', osu_trans('key_1.missing'));
53 $this->assertSame('テスト', osu_trans('key_1.simple'));
54 $this->assertSame('test 2', osu_trans('key_1.simple_empty'));
55 $this->assertSame('test 3', osu_trans('key_1.simple_missing'));
56
57 $this->assertSame('テスト: stuff', osu_trans('key_1.keyed', ['value' => 'stuff']));
58 $this->assertSame('test 2: stuff', osu_trans('key_1.keyed_empty', ['value' => 'stuff']));
59 $this->assertSame('test 3: stuff', osu_trans('key_1.keyed_missing', ['value' => 'stuff']));
60
61 $this->assertSame('1個', osu_trans_choice('key_1.choice', 1));
62 $this->assertSame('2個', osu_trans_choice('key_1.choice', 2));
63 $this->assertSame('1 item', osu_trans_choice('key_1.choice_empty', 1));
64 $this->assertSame('2 items', osu_trans_choice('key_1.choice_empty', 2));
65 $this->assertSame('1 entity', osu_trans_choice('key_1.choice_missing', 1));
66 $this->assertSame('2 entities', osu_trans_choice('key_1.choice_missing', 2));
67 $this->assertSame('', osu_trans('key_1.empty'));
68 $this->assertSame('', osu_trans('key_1.empty_empty'));
69 $this->assertSame('', osu_trans('key_1.empty_missing'));
70 }
71
72 /**
73 * @dataProvider availableLocalesProvider
74 */
75 public function testCorrespondingLocaleFile($locale)
76 {
77 $this->assertNotNull(unmix("js/locales/{$locale}.js"));
78 }
79
80 /**
81 * @dataProvider availableLocalesProvider
82 */
83 public function testCorrespondingMomentLocaleFile($locale)
84 {
85 $this->assertNotNull(unmix('js/moment-locales/'.locale_meta($locale)->moment().'.js'));
86 }
87
88 public function testLocaleApiWithAcceptHeader()
89 {
90 $this
91 ->withHeaders(['accept-language' => 'ja;q=0.6,es,en-US;q=0.8'])
92 ->get(route('api.changelog.index'));
93
94 $this->assertSame('es', App::getLocale());
95 }
96
97 public function testLocaleApiWithAcceptHeaderMagicRespectsUserLang()
98 {
99 $this->actAsScopedUser(User::factory()->create(['user_lang' => 'de']));
100
101 $this
102 ->withHeaders(['accept-language' => '*'])
103 ->get(route('api.changelog.index'));
104
105 $this->assertSame('de', App::getLocale());
106 }
107
108 public function testLocaleApiWithAcceptHeaderOverridesUserLang()
109 {
110 $this->actAsScopedUser(User::factory()->create(['user_lang' => 'de']));
111
112 $this
113 ->withHeaders(['accept-language' => 'ja;q=0.6,es,en-US;q=0.8'])
114 ->get(route('api.changelog.index'));
115
116 $this->assertSame('es', App::getLocale());
117 }
118
119 public function testLocaleWebWithAcceptHeader()
120 {
121 $this
122 ->withHeaders(['accept-language' => 'ja;q=0.6,es,en-US;q=0.8'])
123 ->get('/');
124
125 $this->assertSame('es', App::getLocale());
126 }
127
128 public function testLocaleWebWithAcceptHeaderAndGuestCookie()
129 {
130 $this
131 ->withUnencryptedCookie('locale', 'ja')
132 ->withHeaders(['accept-language' => 'id;q=0.6,pt,en-US;q=0.8'])
133 ->get('/');
134
135 $this->assertSame('ja', App::getLocale());
136 }
137
138 public function testLocaleWebWithAcceptHeaderAndUserLang()
139 {
140 $this
141 ->actingAs(User::factory()->create(['user_lang' => 'fr']))
142 ->withHeaders(['accept-language' => 'ja;q=0.6,es,en-US;q=0.8'])
143 ->get('/');
144
145 $this->assertSame('fr', App::getLocale());
146 }
147
148 public static function availableLocalesProvider()
149 {
150 return array_map(
151 fn ($locale) => [$locale],
152 (require __DIR__.'/../config/app.php')['available_locales'],
153 );
154 }
155}