itube-specs 0.0.1042 → 0.0.1044

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -29,6 +29,7 @@ function getLetter(letter: string) {
29
29
  <style lang="scss">
30
30
  .category-by-letter {
31
31
  display: grid;
32
+ grid-template-columns: minmax(0, 1fr);
32
33
  row-gap: 48px;
33
34
 
34
35
  @include to-br(sm) {
@@ -51,6 +51,7 @@ const { t } = useI18n();
51
51
  .category-list {
52
52
  overflow: hidden;
53
53
  width: 100%;
54
+ min-width: 0;
54
55
 
55
56
  @include to-br(sm) {
56
57
  display: flex;
@@ -88,6 +89,7 @@ const { t } = useI18n();
88
89
  margin-bottom: 6px;
89
90
  padding-block: 4px;
90
91
  width: max-content;
92
+ max-width: 100%;
91
93
  }
92
94
 
93
95
  @include to-br(sm) {
@@ -137,7 +137,7 @@ onBeforeUnmount(() => {
137
137
 
138
138
  const videoCard = computed(() => ({
139
139
  guid: props.data.guid,
140
- title: props.data.header,
140
+ title: props.data.header || props.data.title,
141
141
  duration: props.data.duration,
142
142
  thumbUrls: props.data.thumbUrls,
143
143
  md5: props.data.md5,
@@ -396,6 +396,7 @@ async function onSaveClick() {
396
396
 
397
397
  color: $playlist-add-item-icon;
398
398
  display: flex;
399
+ flex-shrink: 0;
399
400
  align-items: center;
400
401
  column-gap: 4px;
401
402
  }
@@ -72,7 +72,7 @@ const { execute: executeRefresh, loading: loadingRefresh } = useApiAction(Playli
72
72
 
73
73
  /** Плейлисты с ещё не отправленным удалением в попапе добавления не показываем. */
74
74
  const userPlaylists = computed<PaginatedResponse<IPlaylistCard> | null>(() => data.value
75
- ? { ...data.value, items: data.value.items.filter(item => !isPendingDelete(item.id)) }
75
+ ? { ...data.value, items: (data.value.items ?? []).filter(item => !isPendingDelete(item.id)) }
76
76
  : null);
77
77
 
78
78
  async function getUserPlaylists() {
@@ -0,0 +1 @@
1
+ {}
@@ -14,6 +14,7 @@ describe('getCountryPlace', () => {
14
14
  expect(await getCountryPlace('ph', 'de')).toBe('auf den Philippinen');
15
15
  expect(await getCountryPlace('us', 'it')).toBe('negli Stati Uniti');
16
16
  expect(await getCountryPlace('us', 'fr')).toBe('aux États-Unis');
17
+ expect(await getCountryPlace('ph', 'hi')).toBe('फ़िलिपींस में');
17
18
  });
18
19
 
19
20
  it('для локалей без предлога отдаёт именительный падеж — частица живёт в шаблоне', async () => {
@@ -41,7 +42,7 @@ describe('getCountryPlace', () => {
41
42
  it('словари покрывают все локали одним набором кодов', async () => {
42
43
  const codes = Object.keys(en).sort();
43
44
 
44
- for (const locale of ['de', 'es', 'fr', 'it', 'ja', 'ko', 'ru', 'zh']) {
45
+ for (const locale of ['de', 'es', 'fr', 'hi', 'it', 'ja', 'ko', 'ru', 'zh']) {
45
46
  const { default: places } = await import(`../${locale}.json`);
46
47
 
47
48
  expect(Object.keys(places).sort(), locale).toEqual(codes);
@@ -49,7 +50,7 @@ describe('getCountryPlace', () => {
49
50
  });
50
51
 
51
52
  it('именительного падежа не держит — его отдаёт ICU один в один', async () => {
52
- for (const locale of ['de', 'en', 'es', 'fr', 'it', 'ja', 'ko', 'ru', 'zh']) {
53
+ for (const locale of ['de', 'en', 'es', 'fr', 'hi', 'it', 'ja', 'ko', 'ru', 'zh']) {
53
54
  const { default: places } = await import(`../${locale}.json`);
54
55
  const displayNames = new Intl.DisplayNames([locale], { type: 'region' });
55
56
  const missing = Object.keys(places).filter(code => !displayNames.of(code.toUpperCase()));
@@ -0,0 +1,251 @@
1
+ {
2
+ "ad": "एंडोरा में",
3
+ "ae": "संयुक्त अरब अमीरात में",
4
+ "af": "अफ़गानिस्तान में",
5
+ "ag": "एंटिगुआ और बरबुडा में",
6
+ "ai": "एंग्विला में",
7
+ "al": "अल्बानिया में",
8
+ "am": "आर्मेनिया में",
9
+ "ao": "अंगोला में",
10
+ "aq": "अंटार्कटिका में",
11
+ "ar": "अर्जेंटीना में",
12
+ "as": "अमेरिकी समोआ में",
13
+ "at": "ऑस्ट्रिया में",
14
+ "au": "ऑस्ट्रेलिया में",
15
+ "aw": "अरूबा में",
16
+ "ax": "एलैंड द्वीपसमूह में",
17
+ "az": "अज़रबैजान में",
18
+ "ba": "बोस्निया और हर्ज़ेगोविना में",
19
+ "bb": "बारबाडोस में",
20
+ "bd": "बांग्लादेश में",
21
+ "be": "बेल्जियम में",
22
+ "bf": "बुर्किना फ़ासो में",
23
+ "bg": "बुल्गारिया में",
24
+ "bh": "बहरीन में",
25
+ "bi": "बुरुंडी में",
26
+ "bj": "बेनिन में",
27
+ "bl": "सेंट बार्थेलेमी में",
28
+ "bm": "बरमूडा में",
29
+ "bn": "ब्रूनेई में",
30
+ "bo": "बोलीविया में",
31
+ "bq": "कैरिबियन नीदरलैंड में",
32
+ "br": "ब्राज़ील में",
33
+ "bs": "बहामास में",
34
+ "bt": "भूटान में",
35
+ "bv": "बोवेत द्वीप में",
36
+ "bw": "बोत्स्वाना में",
37
+ "by": "बेलारूस में",
38
+ "bz": "बेलीज़ में",
39
+ "ca": "कनाडा में",
40
+ "cc": "कोकोस (कीलिंग) द्वीपसमूह में",
41
+ "cd": "कांगो - किंशासा में",
42
+ "cf": "मध्य अफ़्रीकी गणराज्य में",
43
+ "cg": "कांगो – ब्राज़ाविल में",
44
+ "ch": "स्विट्ज़रलैंड में",
45
+ "ci": "कोत दिवुआर में",
46
+ "ck": "कुक द्वीपसमूह में",
47
+ "cl": "चिली में",
48
+ "cm": "कैमरून में",
49
+ "cn": "चीन में",
50
+ "co": "कोलंबिया में",
51
+ "cr": "कोस्टारिका में",
52
+ "cu": "क्यूबा में",
53
+ "cv": "केप वर्ड में",
54
+ "cw": "कुरासाओ में",
55
+ "cx": "क्रिसमस द्वीप में",
56
+ "cy": "साइप्रस में",
57
+ "cz": "चेकिया में",
58
+ "de": "जर्मनी में",
59
+ "dj": "जिबूती में",
60
+ "dk": "डेनमार्क में",
61
+ "dm": "डोमिनिका में",
62
+ "do": "डोमिनिकन गणराज्य में",
63
+ "dz": "अल्जीरिया में",
64
+ "ec": "इक्वाडोर में",
65
+ "ee": "एस्टोनिया में",
66
+ "eg": "मिस्र में",
67
+ "eh": "पश्चिमी सहारा में",
68
+ "er": "इरिट्रिया में",
69
+ "es": "स्पेन में",
70
+ "et": "इथियोपिया में",
71
+ "fi": "फ़िनलैंड में",
72
+ "fj": "फ़िजी में",
73
+ "fk": "फ़ॉकलैंड द्वीपसमूह में",
74
+ "fm": "माइक्रोनेशिया में",
75
+ "fo": "फ़ेरो द्वीपसमूह में",
76
+ "fr": "फ़्रांस में",
77
+ "ga": "गैबॉन में",
78
+ "gb": "यूनाइटेड किंगडम में",
79
+ "gd": "ग्रेनाडा में",
80
+ "ge": "जॉर्जिया में",
81
+ "gf": "फ़्रेंच गुयाना में",
82
+ "gg": "गर्नसी में",
83
+ "gh": "घाना में",
84
+ "gi": "जिब्राल्टर में",
85
+ "gl": "ग्रीनलैंड में",
86
+ "gm": "गाम्बिया में",
87
+ "gn": "गिनी में",
88
+ "gp": "ग्वाडेलूप में",
89
+ "gq": "इक्वेटोरियल गिनी में",
90
+ "gr": "यूनान में",
91
+ "gs": "दक्षिण जॉर्जिया और दक्षिण सैंडविच द्वीपसमूह में",
92
+ "gt": "ग्वाटेमाला में",
93
+ "gu": "गुआम में",
94
+ "gw": "गिनी-बिसाउ में",
95
+ "gy": "गुयाना में",
96
+ "hk": "हाँग काँग (चीन विशेष प्रशासनिक क्षेत्र) में",
97
+ "hm": "हर्ड द्वीप और मैकडोनॉल्ड द्वीपसमूह में",
98
+ "hn": "होंडूरास में",
99
+ "hr": "क्रोएशिया में",
100
+ "ht": "हैती में",
101
+ "hu": "हंगरी में",
102
+ "id": "इंडोनेशिया में",
103
+ "ie": "आयरलैंड में",
104
+ "il": "इज़राइल में",
105
+ "im": "आइल ऑफ़ मैन में",
106
+ "in": "भारत में",
107
+ "io": "ब्रिटिश हिंद महासागरीय क्षेत्र में",
108
+ "iq": "इराक में",
109
+ "ir": "ईरान में",
110
+ "is": "आइसलैंड में",
111
+ "it": "इटली में",
112
+ "je": "जर्सी में",
113
+ "jm": "जमैका में",
114
+ "jo": "जॉर्डन में",
115
+ "jp": "जापान में",
116
+ "ke": "केन्या में",
117
+ "kg": "किर्गिज़स्तान में",
118
+ "kh": "कंबोडिया में",
119
+ "ki": "किरिबाती में",
120
+ "km": "कोमोरोस में",
121
+ "kn": "सेंट किट्स और नेविस में",
122
+ "kp": "उत्तर कोरिया में",
123
+ "kr": "दक्षिण कोरिया में",
124
+ "kw": "कुवैत में",
125
+ "ky": "कैमेन द्वीपसमूह में",
126
+ "kz": "कज़ाखस्तान में",
127
+ "la": "लाओस में",
128
+ "lb": "लेबनान में",
129
+ "lc": "सेंट लूसिया में",
130
+ "li": "लिचेंस्टीन में",
131
+ "lk": "श्रीलंका में",
132
+ "lr": "लाइबेरिया में",
133
+ "ls": "लेसोथो में",
134
+ "lt": "लिथुआनिया में",
135
+ "lu": "लग्ज़मबर्ग में",
136
+ "lv": "लातविया में",
137
+ "ly": "लीबिया में",
138
+ "ma": "मोरक्को में",
139
+ "mc": "मोनाको में",
140
+ "md": "मॉल्डोवा में",
141
+ "me": "मोंटेनेग्रो में",
142
+ "mf": "सेंट मार्टिन में",
143
+ "mg": "मेडागास्कर में",
144
+ "mh": "मार्शल द्वीपसमूह में",
145
+ "mk": "उत्तरी मकदूनिया में",
146
+ "ml": "माली में",
147
+ "mm": "म्यांमार (बर्मा) में",
148
+ "mn": "मंगोलिया में",
149
+ "mo": "मकाऊ (विशेष प्रशासनिक क्षेत्र चीन) में",
150
+ "mp": "उत्तरी मारियाना द्वीपसमूह में",
151
+ "mq": "मार्टीनिक में",
152
+ "mr": "मॉरिटानिया में",
153
+ "ms": "मोंटसेरात में",
154
+ "mt": "माल्टा में",
155
+ "mu": "मॉरीशस में",
156
+ "mv": "मालदीव में",
157
+ "mw": "मलावी में",
158
+ "mx": "मैक्सिको में",
159
+ "my": "मलेशिया में",
160
+ "mz": "मोज़ांबिक में",
161
+ "na": "नामीबिया में",
162
+ "nc": "न्यू कैलेडोनिया में",
163
+ "ne": "नाइजर में",
164
+ "nf": "नॉरफ़ॉक द्वीप में",
165
+ "ng": "नाइजीरिया में",
166
+ "ni": "निकारागुआ में",
167
+ "nl": "नीदरलैंड में",
168
+ "no": "नॉर्वे में",
169
+ "np": "नेपाल में",
170
+ "nr": "नाउरु में",
171
+ "nu": "नीयू में",
172
+ "nz": "न्यूज़ीलैंड में",
173
+ "om": "ओमान में",
174
+ "pa": "पनामा में",
175
+ "pe": "पेरू में",
176
+ "pf": "फ़्रेंच पोलिनेशिया में",
177
+ "pg": "पापुआ न्यू गिनी में",
178
+ "ph": "फ़िलिपींस में",
179
+ "pk": "पाकिस्तान में",
180
+ "pl": "पोलैंड में",
181
+ "pm": "सेंट पिएरे और मिक्वेलान में",
182
+ "pn": "पिटकैर्न द्वीपसमूह में",
183
+ "pr": "पोर्टो रिको में",
184
+ "ps": "फ़िलिस्तीनी क्षेत्र में",
185
+ "pt": "पुर्तगाल में",
186
+ "pw": "पलाऊ में",
187
+ "py": "पराग्वे में",
188
+ "qa": "क़तर में",
189
+ "re": "रियूनियन में",
190
+ "ro": "रोमानिया में",
191
+ "rs": "सर्बिया में",
192
+ "ru": "रूस में",
193
+ "rw": "रवांडा में",
194
+ "sa": "सऊदी अरब में",
195
+ "sb": "सोलोमन द्वीपसमूह में",
196
+ "sc": "सेशेल्स में",
197
+ "sd": "सूडान में",
198
+ "se": "स्वीडन में",
199
+ "sg": "सिंगापुर में",
200
+ "sh": "सेंट हेलेना में",
201
+ "si": "स्लोवेनिया में",
202
+ "sj": "स्वालबार्ड और जान मायेन में",
203
+ "sk": "स्लोवाकिया में",
204
+ "sl": "सिएरा लियोन में",
205
+ "sm": "सैन मेरीनो में",
206
+ "sn": "सेनेगल में",
207
+ "so": "सोमालिया में",
208
+ "sr": "सूरीनाम में",
209
+ "ss": "दक्षिण सूडान में",
210
+ "st": "साओ टोम और प्रिंसिपे में",
211
+ "sv": "अल सल्वाडोर में",
212
+ "sx": "सिंट मार्टिन में",
213
+ "sy": "सीरिया में",
214
+ "sz": "एस्वाटिनी में",
215
+ "tc": "तुर्क और कैकोज़ द्वीपसमूह में",
216
+ "td": "चाड में",
217
+ "tf": "फ़्रांसीसी दक्षिणी क्षेत्र में",
218
+ "tg": "टोगो में",
219
+ "th": "थाईलैंड में",
220
+ "tj": "ताजिकिस्तान में",
221
+ "tk": "तोकेलाउ में",
222
+ "tl": "तिमोर-लेस्त में",
223
+ "tm": "तुर्कमेनिस्तान में",
224
+ "tn": "ट्यूनीशिया में",
225
+ "to": "टोंगा में",
226
+ "tr": "तुर्किये में",
227
+ "tt": "त्रिनिदाद और टोबैगो में",
228
+ "tv": "तुवालू में",
229
+ "tw": "ताइवान में",
230
+ "tz": "तंज़ानिया में",
231
+ "ua": "यूक्रेन में",
232
+ "ug": "युगांडा में",
233
+ "um": "यू॰एस॰ आउटलाइंग द्वीपसमूह में",
234
+ "us": "संयुक्त राज्य में",
235
+ "uy": "उरूग्वे में",
236
+ "uz": "उज़्बेकिस्तान में",
237
+ "va": "वेटिकन सिटी में",
238
+ "vc": "सेंट विंसेंट और ग्रेनाडाइंस में",
239
+ "ve": "वेनेज़ुएला में",
240
+ "vg": "ब्रिटिश वर्जिन द्वीपसमूह में",
241
+ "vi": "यू॰एस॰ वर्जिन द्वीपसमूह में",
242
+ "vn": "वियतनाम में",
243
+ "vu": "वनुआतू में",
244
+ "wf": "वालिस और फ़्यूचूना में",
245
+ "ws": "समोआ में",
246
+ "ye": "यमन में",
247
+ "yt": "मायोते में",
248
+ "za": "दक्षिण अफ़्रीका में",
249
+ "zm": "ज़ाम्बिया में",
250
+ "zw": "ज़िम्बाब्वे में"
251
+ }
@@ -3,13 +3,14 @@
3
3
  * `in the Philippines`, `auf den Philippinen`, `negli Stati Uniti`, `aux États-Unis`. Предлог,
4
4
  * артикль и падеж лежат в значении — шаблон локали держит только `{secondText}` и ничего не
5
5
  * склеивает. У ja/ko/zh предлога нет, значение — именительный падеж, частица остаётся в шаблоне.
6
+ * У hi послелог `में` стоит в значении после имени (`फ़िलिपींस में`), шаблон его не дописывает.
6
7
  *
7
8
  * Именительного падежа здесь НЕТ намеренно: его один в один отдаёт `Intl.DisplayNames`
8
9
  * (сверено на всех 249 странах × 9 локалях) — см. utils/iso-code-to-country-name.ts. Косвенных
9
10
  * падежей и артиклей в ECMA-402 нет ни в каком виде, поэтому эта таблица и существует.
10
11
  *
11
12
  * Читается ТОЛЬКО на сервере (см. plugins/countries.server.ts): в payload уходит одна готовая
12
- * строка, таблица (249 стран × 9 локалей) в клиентский бандл не попадает. Не реэкспортируется
13
+ * строка, таблица (249 стран × 10 локалей) в клиентский бандл не попадает. Не реэкспортируется
13
14
  * из lib/index.ts по той же причине.
14
15
  */
15
16
  const LOADERS: Record<string, () => Promise<{ default: Record<string, string> }>> = {
@@ -17,6 +18,7 @@ const LOADERS: Record<string, () => Promise<{ default: Record<string, string> }>
17
18
  en: () => import('./en.json'),
18
19
  es: () => import('./es.json'),
19
20
  fr: () => import('./fr.json'),
21
+ hi: () => import('./hi.json'),
20
22
  it: () => import('./it.json'),
21
23
  ja: () => import('./ja.json'),
22
24
  ko: () => import('./ko.json'),
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "itube-specs",
3
3
  "type": "module",
4
- "version": "0.0.1042",
4
+ "version": "0.0.1044",
5
5
  "main": "./nuxt.config.ts",
6
6
  "types": "./types/index.d.ts",
7
7
  "scripts": {
@@ -0,0 +1,15 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { Language, toHeaderLanguage } from '../languages';
3
+
4
+ describe('toHeaderLanguage', () => {
5
+ it('maps locales whose backend code differs from ISO', () => {
6
+ expect(toHeaderLanguage(Language.Japanese)).toBe('jp');
7
+ expect(toHeaderLanguage(Language.Chinese)).toBe('ch');
8
+ expect(toHeaderLanguage(Language.Hindi)).toBe('in');
9
+ });
10
+
11
+ it('passes other locales through as is', () => {
12
+ expect(toHeaderLanguage(Language.English)).toBe('en');
13
+ expect(toHeaderLanguage(Language.Russian)).toBe('ru');
14
+ });
15
+ });
@@ -8,6 +8,7 @@ export const Language = {
8
8
  French: 'fr',
9
9
  Russian: 'ru',
10
10
  Chinese: 'zh',
11
+ Hindi: 'hi',
11
12
  } as const;
12
13
 
13
14
  export type Language = typeof Language[keyof typeof Language];
@@ -15,6 +16,7 @@ export type Language = typeof Language[keyof typeof Language];
15
16
  const languageHeaderMap: Partial<Record<Language, string>> = {
16
17
  [Language.Japanese]: 'jp',
17
18
  [Language.Chinese]: 'ch',
19
+ [Language.Hindi]: 'in',
18
20
  };
19
21
 
20
22
  export function toHeaderLanguage(lang: Language): string {