mirror of
https://example.com
synced 2024-11-22 12:56:39 +09:00
feat: add language picker to post form
Co-authored-by: naskya <m@naskya.net>
This commit is contained in:
parent
8b6f88f7aa
commit
b64d84e7d1
22 changed files with 457 additions and 800 deletions
|
@ -40,6 +40,7 @@
|
|||
|
||||
- マージされていない本家版へのプルリクエストを独断でマージ
|
||||
- RTL Layout Support ([!10452](https://git.joinfirefish.org/firefish/firefish/-/merge_requests/10452))
|
||||
- Add language picker to post form ([!10616](https://git.joinfirefish.org/firefish/firefish/-/merge_requests/10616))
|
||||
- `emojis` の API エンドポイント(Misskey v13- 互換)を追加([firefish-mkdir](https://git.mkdir.uk/hiira/firefish-mkdir) から取り込み)
|
||||
- Docker のベースイメージに Node v21 を使用
|
||||
- HTML のコードに入るコメントアートを削除
|
||||
|
|
|
@ -1171,6 +1171,8 @@ pullDownToReload: "Pull down to reload"
|
|||
enableTimelineStreaming: "Update timelines automatically"
|
||||
useEmojiCdn: "Get Twemoji from CDN"
|
||||
useEmojiCdnDescription: "Use Twemoji from the JSDelivr CDN instead of the server's assets."
|
||||
suggested: "Suggested"
|
||||
noLanguage: "No language"
|
||||
|
||||
_sensitiveMediaDetection:
|
||||
description: "Reduces the effort of server moderation through automatically recognizing
|
||||
|
|
|
@ -2032,6 +2032,8 @@ _iconSets:
|
|||
regular: "標準"
|
||||
fill: "塗りつぶし"
|
||||
duotone: "2色"
|
||||
suggested: "候補"
|
||||
noLanguage: "言語なし"
|
||||
moreUrls: "固定するページ"
|
||||
moreUrlsDescription: "左下のヘルプメニューに固定したいページを以下の形式で、改行区切りで入力してください:\n\"表示名\": https://example.com/"
|
||||
releaseToReload: "離して再読み込み"
|
||||
|
|
|
@ -201,6 +201,9 @@ importers:
|
|||
file-type:
|
||||
specifier: 18.7.0
|
||||
version: 18.7.0
|
||||
firefish-js:
|
||||
specifier: workspace:*
|
||||
version: link:../firefish-js
|
||||
fluent-ffmpeg:
|
||||
specifier: 2.1.2
|
||||
version: 2.1.2
|
||||
|
@ -393,9 +396,6 @@ importers:
|
|||
tinycolor2:
|
||||
specifier: 1.6.0
|
||||
version: 1.6.0
|
||||
tinyld:
|
||||
specifier: 1.3.4
|
||||
version: 1.3.4
|
||||
tmp:
|
||||
specifier: 0.2.1
|
||||
version: 0.2.1
|
||||
|
@ -15760,6 +15760,7 @@ packages:
|
|||
resolution: {integrity: sha512-u26CNoaInA4XpDU+8s/6Cq8xHc2T5M4fXB3ICfXPokUQoLzmPgSZU02TAkFwFMJCWTjk53gtkS8pETTreZwCqw==}
|
||||
engines: {node: '>= 12.10.0', npm: '>= 6.12.0', yarn: '>= 1.20.0'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/titleize@3.0.0:
|
||||
resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==}
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
"feed": "4.2.2",
|
||||
"file-type": "18.7.0",
|
||||
"fluent-ffmpeg": "2.1.2",
|
||||
"firefish-js": "workspace:*",
|
||||
"got": "13.0.0",
|
||||
"gunzip-maybe": "1.4.2",
|
||||
"happy-dom": "12.10.3",
|
||||
|
@ -125,7 +126,6 @@
|
|||
"tar-stream": "3.1.6",
|
||||
"tesseract.js": "5.0.3",
|
||||
"tinycolor2": "1.6.0",
|
||||
"tinyld": "1.3.4",
|
||||
"tmp": "0.2.1",
|
||||
"typeorm": "0.3.17",
|
||||
"ulid": "2.3.0",
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
import { detect } from "tinyld";
|
||||
import * as mfm from "mfm-js";
|
||||
|
||||
export default function detectLanguage(text: string): string {
|
||||
const nodes = mfm.parse(text);
|
||||
const filtered = mfm.extract(nodes, (node) => {
|
||||
return node.type === "text" || node.type === "quote";
|
||||
});
|
||||
const purified = mfm.toString(filtered);
|
||||
return detect(purified);
|
||||
}
|
|
@ -1,217 +1,71 @@
|
|||
// TODO: sharedに置いてフロントエンドのと統合したい
|
||||
export const langmap = {
|
||||
ach: {
|
||||
nativeName: "Lwo",
|
||||
},
|
||||
ady: {
|
||||
nativeName: "Адыгэбзэ",
|
||||
},
|
||||
export const iso639Langs1 = {
|
||||
af: {
|
||||
nativeName: "Afrikaans",
|
||||
},
|
||||
"af-NA": {
|
||||
nativeName: "Afrikaans (Namibia)",
|
||||
},
|
||||
"af-ZA": {
|
||||
nativeName: "Afrikaans (South Africa)",
|
||||
},
|
||||
ak: {
|
||||
nativeName: "Tɕɥi",
|
||||
},
|
||||
ar: {
|
||||
nativeName: "العربية",
|
||||
rtl: true,
|
||||
},
|
||||
"ar-AR": {
|
||||
nativeName: "العربية",
|
||||
},
|
||||
"ar-MA": {
|
||||
nativeName: "العربية",
|
||||
},
|
||||
"ar-SA": {
|
||||
nativeName: "العربية (السعودية)",
|
||||
},
|
||||
"ay-BO": {
|
||||
ay: {
|
||||
nativeName: "Aymar aru",
|
||||
},
|
||||
az: {
|
||||
nativeName: "Azərbaycan dili",
|
||||
},
|
||||
"az-AZ": {
|
||||
nativeName: "Azərbaycan dili",
|
||||
},
|
||||
"be-BY": {
|
||||
be: {
|
||||
nativeName: "Беларуская",
|
||||
},
|
||||
bg: {
|
||||
nativeName: "Български",
|
||||
},
|
||||
"bg-BG": {
|
||||
nativeName: "Български",
|
||||
},
|
||||
bn: {
|
||||
nativeName: "বাংলা",
|
||||
},
|
||||
"bn-IN": {
|
||||
nativeName: "বাংলা (ভারত)",
|
||||
},
|
||||
"bn-BD": {
|
||||
nativeName: "বাংলা(বাংলাদেশ)",
|
||||
},
|
||||
br: {
|
||||
nativeName: "Brezhoneg",
|
||||
},
|
||||
"bs-BA": {
|
||||
bs: {
|
||||
nativeName: "Bosanski",
|
||||
},
|
||||
ca: {
|
||||
nativeName: "Català",
|
||||
},
|
||||
"ca-ES": {
|
||||
nativeName: "Català",
|
||||
},
|
||||
cak: {
|
||||
nativeName: "Maya Kaqchikel",
|
||||
},
|
||||
"ck-US": {
|
||||
nativeName: "ᏣᎳᎩ (tsalagi)",
|
||||
},
|
||||
cs: {
|
||||
nativeName: "Čeština",
|
||||
},
|
||||
"cs-CZ": {
|
||||
nativeName: "Čeština",
|
||||
},
|
||||
cy: {
|
||||
nativeName: "Cymraeg",
|
||||
},
|
||||
"cy-GB": {
|
||||
nativeName: "Cymraeg",
|
||||
},
|
||||
da: {
|
||||
nativeName: "Dansk",
|
||||
},
|
||||
"da-DK": {
|
||||
nativeName: "Dansk",
|
||||
},
|
||||
de: {
|
||||
nativeName: "Deutsch",
|
||||
},
|
||||
"de-AT": {
|
||||
nativeName: "Deutsch (Österreich)",
|
||||
},
|
||||
"de-DE": {
|
||||
nativeName: "Deutsch (Deutschland)",
|
||||
},
|
||||
"de-CH": {
|
||||
nativeName: "Deutsch (Schweiz)",
|
||||
},
|
||||
dsb: {
|
||||
nativeName: "Dolnoserbšćina",
|
||||
},
|
||||
el: {
|
||||
nativeName: "Ελληνικά",
|
||||
},
|
||||
"el-GR": {
|
||||
nativeName: "Ελληνικά",
|
||||
},
|
||||
en: {
|
||||
nativeName: "English",
|
||||
},
|
||||
"en-GB": {
|
||||
nativeName: "English (UK)",
|
||||
},
|
||||
"en-AU": {
|
||||
nativeName: "English (Australia)",
|
||||
},
|
||||
"en-CA": {
|
||||
nativeName: "English (Canada)",
|
||||
},
|
||||
"en-IE": {
|
||||
nativeName: "English (Ireland)",
|
||||
},
|
||||
"en-IN": {
|
||||
nativeName: "English (India)",
|
||||
},
|
||||
"en-PI": {
|
||||
nativeName: "English (Pirate)",
|
||||
},
|
||||
"en-SG": {
|
||||
nativeName: "English (Singapore)",
|
||||
},
|
||||
"en-UD": {
|
||||
nativeName: "English (Upside Down)",
|
||||
},
|
||||
"en-US": {
|
||||
nativeName: "English (US)",
|
||||
},
|
||||
"en-ZA": {
|
||||
nativeName: "English (South Africa)",
|
||||
},
|
||||
"en@pirate": {
|
||||
nativeName: "English (Pirate)",
|
||||
},
|
||||
eo: {
|
||||
nativeName: "Esperanto",
|
||||
},
|
||||
"eo-EO": {
|
||||
nativeName: "Esperanto",
|
||||
},
|
||||
es: {
|
||||
nativeName: "Español",
|
||||
},
|
||||
"es-AR": {
|
||||
nativeName: "Español (Argentine)",
|
||||
},
|
||||
"es-419": {
|
||||
nativeName: "Español (Latinoamérica)",
|
||||
},
|
||||
"es-CL": {
|
||||
nativeName: "Español (Chile)",
|
||||
},
|
||||
"es-CO": {
|
||||
nativeName: "Español (Colombia)",
|
||||
},
|
||||
"es-EC": {
|
||||
nativeName: "Español (Ecuador)",
|
||||
},
|
||||
"es-ES": {
|
||||
nativeName: "Español (España)",
|
||||
},
|
||||
"es-LA": {
|
||||
nativeName: "Español (Latinoamérica)",
|
||||
},
|
||||
"es-NI": {
|
||||
nativeName: "Español (Nicaragua)",
|
||||
},
|
||||
"es-MX": {
|
||||
nativeName: "Español (México)",
|
||||
},
|
||||
"es-US": {
|
||||
nativeName: "Español (Estados Unidos)",
|
||||
},
|
||||
"es-VE": {
|
||||
nativeName: "Español (Venezuela)",
|
||||
},
|
||||
et: {
|
||||
nativeName: "eesti keel",
|
||||
},
|
||||
"et-EE": {
|
||||
nativeName: "Eesti (Estonia)",
|
||||
},
|
||||
eu: {
|
||||
nativeName: "Euskara",
|
||||
},
|
||||
"eu-ES": {
|
||||
nativeName: "Euskara",
|
||||
},
|
||||
fa: {
|
||||
nativeName: "فارسی",
|
||||
},
|
||||
"fa-IR": {
|
||||
nativeName: "فارسی",
|
||||
},
|
||||
"fb-LT": {
|
||||
nativeName: "Leet Speak",
|
||||
rtl: true,
|
||||
},
|
||||
ff: {
|
||||
nativeName: "Fulah",
|
||||
|
@ -219,154 +73,86 @@ export const langmap = {
|
|||
fi: {
|
||||
nativeName: "Suomi",
|
||||
},
|
||||
"fi-FI": {
|
||||
nativeName: "Suomi",
|
||||
},
|
||||
fo: {
|
||||
nativeName: "Føroyskt",
|
||||
},
|
||||
"fo-FO": {
|
||||
nativeName: "Føroyskt (Færeyjar)",
|
||||
},
|
||||
fr: {
|
||||
nativeName: "Français",
|
||||
},
|
||||
"fr-CA": {
|
||||
nativeName: "Français (Canada)",
|
||||
},
|
||||
"fr-FR": {
|
||||
nativeName: "Français (France)",
|
||||
},
|
||||
"fr-BE": {
|
||||
nativeName: "Français (Belgique)",
|
||||
},
|
||||
"fr-CH": {
|
||||
nativeName: "Français (Suisse)",
|
||||
},
|
||||
"fy-NL": {
|
||||
fy: {
|
||||
nativeName: "Frysk",
|
||||
},
|
||||
ga: {
|
||||
nativeName: "Gaeilge",
|
||||
},
|
||||
"ga-IE": {
|
||||
nativeName: "Gaeilge",
|
||||
},
|
||||
gd: {
|
||||
nativeName: "Gàidhlig",
|
||||
},
|
||||
gl: {
|
||||
nativeName: "Galego",
|
||||
},
|
||||
"gl-ES": {
|
||||
nativeName: "Galego",
|
||||
},
|
||||
"gn-PY": {
|
||||
gn: {
|
||||
nativeName: "Avañe'ẽ",
|
||||
},
|
||||
"gu-IN": {
|
||||
gu: {
|
||||
nativeName: "ગુજરાતી",
|
||||
},
|
||||
gv: {
|
||||
nativeName: "Gaelg",
|
||||
},
|
||||
"gx-GR": {
|
||||
nativeName: "Ἑλληνική ἀρχαία",
|
||||
},
|
||||
he: {
|
||||
nativeName: "עברית",
|
||||
},
|
||||
"he-IL": {
|
||||
nativeName: "עברית",
|
||||
rtl: true,
|
||||
},
|
||||
hi: {
|
||||
nativeName: "हिन्दी",
|
||||
},
|
||||
"hi-IN": {
|
||||
nativeName: "हिन्दी",
|
||||
},
|
||||
hr: {
|
||||
nativeName: "Hrvatski",
|
||||
},
|
||||
"hr-HR": {
|
||||
nativeName: "Hrvatski",
|
||||
},
|
||||
hsb: {
|
||||
nativeName: "Hornjoserbšćina",
|
||||
},
|
||||
ht: {
|
||||
nativeName: "Kreyòl",
|
||||
},
|
||||
hu: {
|
||||
nativeName: "Magyar",
|
||||
},
|
||||
"hu-HU": {
|
||||
nativeName: "Magyar",
|
||||
},
|
||||
hy: {
|
||||
nativeName: "Հայերեն",
|
||||
},
|
||||
"hy-AM": {
|
||||
nativeName: "Հայերեն (Հայաստան)",
|
||||
},
|
||||
id: {
|
||||
nativeName: "Bahasa Indonesia",
|
||||
},
|
||||
"id-ID": {
|
||||
nativeName: "Bahasa Indonesia",
|
||||
},
|
||||
is: {
|
||||
nativeName: "Íslenska",
|
||||
},
|
||||
"is-IS": {
|
||||
nativeName: "Íslenska (Iceland)",
|
||||
},
|
||||
it: {
|
||||
nativeName: "Italiano",
|
||||
},
|
||||
"it-IT": {
|
||||
nativeName: "Italiano",
|
||||
},
|
||||
ja: {
|
||||
nativeName: "日本語",
|
||||
},
|
||||
"ja-JP": {
|
||||
nativeName: "日本語 (日本)",
|
||||
},
|
||||
"jv-ID": {
|
||||
jv: {
|
||||
nativeName: "Basa Jawa",
|
||||
},
|
||||
"ka-GE": {
|
||||
ka: {
|
||||
nativeName: "ქართული",
|
||||
},
|
||||
"kk-KZ": {
|
||||
kk: {
|
||||
nativeName: "Қазақша",
|
||||
},
|
||||
km: {
|
||||
nativeName: "ភាសាខ្មែរ",
|
||||
},
|
||||
kl: {
|
||||
nativeName: "kalaallisut",
|
||||
},
|
||||
"km-KH": {
|
||||
km: {
|
||||
nativeName: "ភាសាខ្មែរ",
|
||||
},
|
||||
kab: {
|
||||
nativeName: "Taqbaylit",
|
||||
},
|
||||
kn: {
|
||||
nativeName: "ಕನ್ನಡ",
|
||||
},
|
||||
"kn-IN": {
|
||||
nativeName: "ಕನ್ನಡ (India)",
|
||||
},
|
||||
ko: {
|
||||
nativeName: "한국어",
|
||||
},
|
||||
"ko-KR": {
|
||||
nativeName: "한국어 (한국)",
|
||||
},
|
||||
"ku-TR": {
|
||||
ku: {
|
||||
nativeName: "Kurdî",
|
||||
},
|
||||
kw: {
|
||||
|
@ -375,66 +161,39 @@ export const langmap = {
|
|||
la: {
|
||||
nativeName: "Latin",
|
||||
},
|
||||
"la-VA": {
|
||||
nativeName: "Latin",
|
||||
},
|
||||
lb: {
|
||||
nativeName: "Lëtzebuergesch",
|
||||
},
|
||||
"li-NL": {
|
||||
li: {
|
||||
nativeName: "Lèmbörgs",
|
||||
},
|
||||
lt: {
|
||||
nativeName: "Lietuvių",
|
||||
},
|
||||
"lt-LT": {
|
||||
nativeName: "Lietuvių",
|
||||
},
|
||||
lv: {
|
||||
nativeName: "Latviešu",
|
||||
},
|
||||
"lv-LV": {
|
||||
nativeName: "Latviešu",
|
||||
},
|
||||
mai: {
|
||||
nativeName: "मैथिली, মৈথিলী",
|
||||
},
|
||||
"mg-MG": {
|
||||
mg: {
|
||||
nativeName: "Malagasy",
|
||||
},
|
||||
mk: {
|
||||
nativeName: "Македонски",
|
||||
},
|
||||
"mk-MK": {
|
||||
nativeName: "Македонски (Македонски)",
|
||||
},
|
||||
ml: {
|
||||
nativeName: "മലയാളം",
|
||||
},
|
||||
"ml-IN": {
|
||||
nativeName: "മലയാളം",
|
||||
},
|
||||
"mn-MN": {
|
||||
mn: {
|
||||
nativeName: "Монгол",
|
||||
},
|
||||
mr: {
|
||||
nativeName: "मराठी",
|
||||
},
|
||||
"mr-IN": {
|
||||
nativeName: "मराठी",
|
||||
},
|
||||
ms: {
|
||||
nativeName: "Bahasa Melayu",
|
||||
},
|
||||
"ms-MY": {
|
||||
nativeName: "Bahasa Melayu",
|
||||
},
|
||||
mt: {
|
||||
nativeName: "Malti",
|
||||
},
|
||||
"mt-MT": {
|
||||
nativeName: "Malti",
|
||||
},
|
||||
my: {
|
||||
nativeName: "ဗမာစကာ",
|
||||
},
|
||||
|
@ -444,223 +203,179 @@ export const langmap = {
|
|||
nb: {
|
||||
nativeName: "Norsk (bokmål)",
|
||||
},
|
||||
"nb-NO": {
|
||||
nativeName: "Norsk (bokmål)",
|
||||
},
|
||||
ne: {
|
||||
nativeName: "नेपाली",
|
||||
},
|
||||
"ne-NP": {
|
||||
nativeName: "नेपाली",
|
||||
},
|
||||
nl: {
|
||||
nativeName: "Nederlands",
|
||||
},
|
||||
"nl-BE": {
|
||||
nativeName: "Nederlands (België)",
|
||||
},
|
||||
"nl-NL": {
|
||||
nativeName: "Nederlands (Nederland)",
|
||||
},
|
||||
"nn-NO": {
|
||||
nn: {
|
||||
nativeName: "Norsk (nynorsk)",
|
||||
},
|
||||
oc: {
|
||||
nativeName: "Occitan",
|
||||
},
|
||||
"or-IN": {
|
||||
or: {
|
||||
nativeName: "ଓଡ଼ିଆ",
|
||||
},
|
||||
pa: {
|
||||
nativeName: "ਪੰਜਾਬੀ",
|
||||
},
|
||||
"pa-IN": {
|
||||
nativeName: "ਪੰਜਾਬੀ (ਭਾਰਤ ਨੂੰ)",
|
||||
},
|
||||
pl: {
|
||||
nativeName: "Polski",
|
||||
},
|
||||
"pl-PL": {
|
||||
nativeName: "Polski",
|
||||
},
|
||||
"ps-AF": {
|
||||
ps: {
|
||||
nativeName: "پښتو",
|
||||
rtl: true,
|
||||
},
|
||||
pt: {
|
||||
nativeName: "Português",
|
||||
},
|
||||
"pt-BR": {
|
||||
nativeName: "Português (Brasil)",
|
||||
},
|
||||
"pt-PT": {
|
||||
nativeName: "Português (Portugal)",
|
||||
},
|
||||
"qu-PE": {
|
||||
qu: {
|
||||
nativeName: "Qhichwa",
|
||||
},
|
||||
"rm-CH": {
|
||||
rm: {
|
||||
nativeName: "Rumantsch",
|
||||
},
|
||||
ro: {
|
||||
nativeName: "Română",
|
||||
},
|
||||
"ro-RO": {
|
||||
nativeName: "Română",
|
||||
},
|
||||
ru: {
|
||||
nativeName: "Русский",
|
||||
},
|
||||
"ru-RU": {
|
||||
nativeName: "Русский",
|
||||
},
|
||||
"sa-IN": {
|
||||
sa: {
|
||||
nativeName: "संस्कृतम्",
|
||||
},
|
||||
"se-NO": {
|
||||
se: {
|
||||
nativeName: "Davvisámegiella",
|
||||
},
|
||||
sh: {
|
||||
nativeName: "српскохрватски",
|
||||
},
|
||||
"si-LK": {
|
||||
si: {
|
||||
nativeName: "සිංහල",
|
||||
},
|
||||
sk: {
|
||||
nativeName: "Slovenčina",
|
||||
},
|
||||
"sk-SK": {
|
||||
nativeName: "Slovenčina (Slovakia)",
|
||||
},
|
||||
sl: {
|
||||
nativeName: "Slovenščina",
|
||||
},
|
||||
"sl-SI": {
|
||||
nativeName: "Slovenščina",
|
||||
},
|
||||
"so-SO": {
|
||||
so: {
|
||||
nativeName: "Soomaaliga",
|
||||
},
|
||||
sq: {
|
||||
nativeName: "Shqip",
|
||||
},
|
||||
"sq-AL": {
|
||||
nativeName: "Shqip",
|
||||
},
|
||||
sr: {
|
||||
nativeName: "Српски",
|
||||
},
|
||||
"sr-RS": {
|
||||
nativeName: "Српски (Serbia)",
|
||||
},
|
||||
su: {
|
||||
nativeName: "Basa Sunda",
|
||||
},
|
||||
sv: {
|
||||
nativeName: "Svenska",
|
||||
},
|
||||
"sv-SE": {
|
||||
nativeName: "Svenska",
|
||||
},
|
||||
sw: {
|
||||
nativeName: "Kiswahili",
|
||||
},
|
||||
"sw-KE": {
|
||||
nativeName: "Kiswahili",
|
||||
},
|
||||
ta: {
|
||||
nativeName: "தமிழ்",
|
||||
},
|
||||
"ta-IN": {
|
||||
nativeName: "தமிழ்",
|
||||
},
|
||||
te: {
|
||||
nativeName: "తెలుగు",
|
||||
},
|
||||
"te-IN": {
|
||||
nativeName: "తెలుగు",
|
||||
},
|
||||
tg: {
|
||||
nativeName: "забо́ни тоҷикӣ́",
|
||||
},
|
||||
"tg-TJ": {
|
||||
nativeName: "тоҷикӣ",
|
||||
},
|
||||
th: {
|
||||
nativeName: "ภาษาไทย",
|
||||
},
|
||||
"th-TH": {
|
||||
nativeName: "ภาษาไทย (ประเทศไทย)",
|
||||
},
|
||||
fil: {
|
||||
nativeName: "Filipino",
|
||||
},
|
||||
tlh: {
|
||||
nativeName: "tlhIngan-Hol",
|
||||
},
|
||||
tr: {
|
||||
nativeName: "Türkçe",
|
||||
},
|
||||
"tr-TR": {
|
||||
nativeName: "Türkçe",
|
||||
},
|
||||
"tt-RU": {
|
||||
tt: {
|
||||
nativeName: "татарча",
|
||||
},
|
||||
uk: {
|
||||
nativeName: "Українська",
|
||||
},
|
||||
"uk-UA": {
|
||||
nativeName: "Українська",
|
||||
},
|
||||
ur: {
|
||||
nativeName: "اردو",
|
||||
},
|
||||
"ur-PK": {
|
||||
nativeName: "اردو",
|
||||
rtl: true,
|
||||
},
|
||||
uz: {
|
||||
nativeName: "O'zbek",
|
||||
},
|
||||
"uz-UZ": {
|
||||
nativeName: "O'zbek",
|
||||
},
|
||||
vi: {
|
||||
nativeName: "Tiếng Việt",
|
||||
},
|
||||
"vi-VN": {
|
||||
nativeName: "Tiếng Việt",
|
||||
},
|
||||
"xh-ZA": {
|
||||
xh: {
|
||||
nativeName: "isiXhosa",
|
||||
},
|
||||
yi: {
|
||||
nativeName: "ייִדיש",
|
||||
},
|
||||
"yi-DE": {
|
||||
nativeName: "ייִדיש (German)",
|
||||
rtl: true,
|
||||
},
|
||||
zh: {
|
||||
nativeName: "中文",
|
||||
},
|
||||
"zh-Hans": {
|
||||
nativeName: "中文简体",
|
||||
},
|
||||
"zh-Hant": {
|
||||
nativeName: "中文繁體",
|
||||
},
|
||||
"zh-CN": {
|
||||
nativeName: "中文(中国大陆)",
|
||||
},
|
||||
"zh-HK": {
|
||||
nativeName: "中文(香港)",
|
||||
},
|
||||
"zh-SG": {
|
||||
nativeName: "中文(新加坡)",
|
||||
},
|
||||
"zh-TW": {
|
||||
nativeName: "中文(台灣)",
|
||||
},
|
||||
"zu-ZA": {
|
||||
zu: {
|
||||
nativeName: "isiZulu",
|
||||
},
|
||||
};
|
||||
|
||||
export const iso639Langs3 = {
|
||||
ach: {
|
||||
nativeName: "Lwo",
|
||||
},
|
||||
ady: {
|
||||
nativeName: "Адыгэбзэ",
|
||||
},
|
||||
cak: {
|
||||
nativeName: "Maya Kaqchikel",
|
||||
},
|
||||
chr: {
|
||||
nativeName: "ᏣᎳᎩ (tsalagi)",
|
||||
},
|
||||
dsb: {
|
||||
nativeName: "Dolnoserbšćina",
|
||||
},
|
||||
fil: {
|
||||
nativeName: "Filipino",
|
||||
},
|
||||
hsb: {
|
||||
nativeName: "Hornjoserbšćina",
|
||||
},
|
||||
kab: {
|
||||
nativeName: "Taqbaylit",
|
||||
},
|
||||
mai: {
|
||||
nativeName: "मैथिली, মৈথিলী",
|
||||
},
|
||||
tlh: {
|
||||
nativeName: "tlhIngan-Hol",
|
||||
},
|
||||
tok: {
|
||||
nativeName: "Toki Pona",
|
||||
},
|
||||
yue: {
|
||||
nativeName: "粵語",
|
||||
},
|
||||
nan: {
|
||||
nativeName: "閩南語",
|
||||
},
|
||||
};
|
||||
|
||||
export const langmapNoRegion = Object.assign({}, iso639Langs1, iso639Langs3);
|
||||
|
||||
export const iso639Regional = {
|
||||
"zh-hans": {
|
||||
nativeName: "中文(简体)",
|
||||
},
|
||||
"zh-hant": {
|
||||
nativeName: "中文(繁體)",
|
||||
},
|
||||
};
|
||||
|
||||
export const langmap = Object.assign({}, langmapNoRegion, iso639Regional);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { langmap } from "@/misc/langmap.js";
|
||||
|
||||
export const packedNoteSchema = {
|
||||
type: "object",
|
||||
properties: {
|
||||
|
@ -19,6 +21,11 @@ export const packedNoteSchema = {
|
|||
optional: false,
|
||||
nullable: true,
|
||||
},
|
||||
lang: {
|
||||
type: "string",
|
||||
enum: [...Object.keys(langmap)],
|
||||
nullable: true,
|
||||
},
|
||||
cw: {
|
||||
type: "string",
|
||||
optional: true,
|
||||
|
|
|
@ -309,16 +309,13 @@ export async function createNote(
|
|||
) {
|
||||
text = note.source.content;
|
||||
if (note.contentMap != null) {
|
||||
const key = Object.keys(note.contentMap)[0];
|
||||
lang = Object.keys(langmap).includes(key)
|
||||
? key.trim().split("-")[0].split("@")[0]
|
||||
: null;
|
||||
const key = Object.keys(note.contentMap)[0].toLowerCase();
|
||||
lang = Object.keys(langmap).includes(key) ? key : null;
|
||||
}
|
||||
} else if (note.contentMap != null) {
|
||||
const entry = Object.entries(note.contentMap)[0];
|
||||
lang = Object.keys(langmap).includes(entry[0])
|
||||
? entry[0].trim().split("-")[0].split("@")[0]
|
||||
: null;
|
||||
const key = entry[0].toLowerCase();
|
||||
lang = Object.keys(langmap).includes(key) ? key : null;
|
||||
text = htmlToMfm(entry[1], note.tag);
|
||||
} else if (typeof note.content === "string") {
|
||||
text = htmlToMfm(note.content, note.tag);
|
||||
|
@ -584,15 +581,12 @@ export async function updateNote(value: string | IObject, resolver?: Resolver) {
|
|||
text = post.source.content;
|
||||
if (post.contentMap != null) {
|
||||
const key = Object.keys(post.contentMap)[0];
|
||||
lang = Object.keys(langmap).includes(key)
|
||||
? key.trim().split("-")[0].split("@")[0]
|
||||
: null;
|
||||
lang = Object.keys(langmap).includes(key) ? key : null;
|
||||
}
|
||||
} else if (post.contentMap != null) {
|
||||
const entry = Object.entries(post.contentMap)[0];
|
||||
lang = Object.keys(langmap).includes(entry[0])
|
||||
? entry[0].trim().split("-")[0].split("@")[0]
|
||||
: null;
|
||||
const key = entry[0].toLowerCase();
|
||||
lang = Object.keys(langmap).includes(key) ? key : null;
|
||||
text = htmlToMfm(entry[1], post.tag);
|
||||
} else if (typeof post.content === "string") {
|
||||
text = htmlToMfm(post.content, post.tag);
|
||||
|
|
|
@ -6,7 +6,6 @@ import { DriveFiles, Notes, Users, Emojis, Polls } from "@/models/index.js";
|
|||
import type { Emoji } from "@/models/entities/emoji.js";
|
||||
import type { Poll } from "@/models/entities/poll.js";
|
||||
import toHtml from "@/remote/activitypub/misc/get-note-html.js";
|
||||
import detectLanguage from "@/misc/detect-language.js";
|
||||
import renderEmoji from "./emoji.js";
|
||||
import renderMention from "./mention.js";
|
||||
import renderHashtag from "./hashtag.js";
|
||||
|
@ -115,10 +114,9 @@ export default async function renderNote(
|
|||
}),
|
||||
);
|
||||
|
||||
const lang = note.lang ?? detectLanguage(text);
|
||||
const contentMap = lang
|
||||
const contentMap = note.lang
|
||||
? {
|
||||
[lang]: content,
|
||||
[note.lang]: content,
|
||||
}
|
||||
: null;
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ export const paramDef = {
|
|||
birthday: { ...Users.birthdaySchema, nullable: true },
|
||||
lang: {
|
||||
type: "string",
|
||||
enum: [null, ...Object.keys(langmap)],
|
||||
enum: Object.keys(langmap),
|
||||
nullable: true,
|
||||
},
|
||||
avatarId: { type: "string", format: "misskey:id", nullable: true },
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { In } from "typeorm";
|
||||
import create from "@/services/note/create.js";
|
||||
import { langmap } from "@/misc/langmap.js";
|
||||
import type { User } from "@/models/entities/user.js";
|
||||
import {
|
||||
Users,
|
||||
|
@ -108,7 +109,11 @@ export const paramDef = {
|
|||
},
|
||||
},
|
||||
text: { type: "string", maxLength: MAX_NOTE_TEXT_LENGTH, nullable: true },
|
||||
lang: { type: "string", nullable: true, maxLength: 10 },
|
||||
lang: {
|
||||
type: "string",
|
||||
enum: Object.keys(langmap),
|
||||
nullable: true,
|
||||
},
|
||||
cw: { type: "string", nullable: true, maxLength: 100 },
|
||||
localOnly: { type: "boolean", default: false },
|
||||
noExtractMentions: { type: "boolean", default: false },
|
||||
|
|
|
@ -35,7 +35,6 @@ import renderUpdate from "@/remote/activitypub/renderer/update.js";
|
|||
import { deliverToRelays } from "@/services/relay.js";
|
||||
// import { deliverQuestionUpdate } from "@/services/note/polls/update.js";
|
||||
import { langmap } from "@/misc/langmap.js";
|
||||
import detectLanguage from "@/misc/detect-language.js";
|
||||
|
||||
export const meta = {
|
||||
tags: ["notes"],
|
||||
|
@ -170,7 +169,11 @@ export const paramDef = {
|
|||
},
|
||||
},
|
||||
text: { type: "string", maxLength: MAX_NOTE_TEXT_LENGTH, nullable: true },
|
||||
lang: { type: "string", nullable: true, maxLength: 10 },
|
||||
lang: {
|
||||
type: "string",
|
||||
enum: Object.keys(langmap),
|
||||
nullable: true,
|
||||
},
|
||||
cw: { type: "string", nullable: true, maxLength: 250 },
|
||||
localOnly: { type: "boolean", default: false },
|
||||
noExtractMentions: { type: "boolean", default: false },
|
||||
|
@ -378,11 +381,9 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
}
|
||||
|
||||
if (ps.lang) {
|
||||
if (!Object.keys(langmap).includes(ps.lang.trim()))
|
||||
if (!Object.keys(langmap).includes(ps.lang.toLowerCase()))
|
||||
throw new Error("invalid param");
|
||||
ps.lang = ps.lang.trim().split("-")[0].split("@")[0];
|
||||
} else if (ps.text) {
|
||||
ps.lang = detectLanguage(ps.text);
|
||||
ps.lang = ps.lang.toLowerCase();
|
||||
} else {
|
||||
ps.lang = null;
|
||||
}
|
||||
|
|
|
@ -63,7 +63,6 @@ import meilisearch from "@/db/meilisearch.js";
|
|||
import { redisClient } from "@/db/redis.js";
|
||||
import { Mutex } from "redis-semaphore";
|
||||
import { langmap } from "@/misc/langmap.js";
|
||||
import detectLanguage from "@/misc/detect-language.js";
|
||||
|
||||
const mutedWordsCache = new Cache<
|
||||
{ userId: UserProfile["userId"]; mutedWords: UserProfile["mutedWords"] }[]
|
||||
|
@ -276,11 +275,9 @@ export default async (
|
|||
}
|
||||
|
||||
if (data.lang) {
|
||||
if (!Object.keys(langmap).includes(data.lang.trim()))
|
||||
if (!Object.keys(langmap).includes(data.lang.toLowerCase()))
|
||||
throw new Error("invalid param");
|
||||
data.lang = data.lang.trim().split("-")[0].split("@")[0];
|
||||
} else if (data.text) {
|
||||
data.lang = detectLanguage(data.text);
|
||||
data.lang = data.lang.toLowerCase();
|
||||
} else {
|
||||
data.lang = null;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,21 @@
|
|||
><i :class="icon('ph-eye-slash')"></i
|
||||
></span>
|
||||
</button>
|
||||
<button
|
||||
ref="languageButton"
|
||||
v-tooltip="i18n.ts.language"
|
||||
class="_button language"
|
||||
@click="setLanguage"
|
||||
>
|
||||
<i
|
||||
v-if="language === '' || language == null"
|
||||
class="_button"
|
||||
:class="icon('ph-seal-warning')"
|
||||
></i>
|
||||
<p v-else class="_button" style="font-weight: bold">
|
||||
{{ language.split("-")[0] }}
|
||||
</p>
|
||||
</button>
|
||||
<button
|
||||
v-tooltip="i18n.ts.previewNoteText"
|
||||
class="_button preview"
|
||||
|
@ -293,6 +308,9 @@ import { uploadFile } from "@/scripts/upload";
|
|||
import { deepClone } from "@/scripts/clone";
|
||||
import preprocess from "@/scripts/preprocess";
|
||||
import { vibrate } from "@/scripts/vibrate";
|
||||
import { langmap } from "@/scripts/langmap";
|
||||
import { MenuItem } from "@/types/menu";
|
||||
import detectLanguage from "@/scripts/detect-language";
|
||||
import icon from "@/scripts/icon";
|
||||
|
||||
const modal = inject("modal");
|
||||
|
@ -306,6 +324,7 @@ const props = withDefaults(
|
|||
specified?: firefish.entities.User;
|
||||
initialText?: string;
|
||||
initialVisibility?: typeof firefish.noteVisibilities;
|
||||
initialLanguage?: typeof firefish.languages;
|
||||
initialFiles?: firefish.entities.DriveFile[];
|
||||
initialLocalOnly?: boolean;
|
||||
initialVisibleUsers?: firefish.entities.User[];
|
||||
|
@ -333,6 +352,7 @@ const textareaEl = ref<HTMLTextAreaElement | null>(null);
|
|||
const cwInputEl = ref<HTMLInputElement | null>(null);
|
||||
const hashtagsInputEl = ref<HTMLInputElement | null>(null);
|
||||
const visibilityButton = ref<HTMLElement | null>(null);
|
||||
const languageButton = ref<HTMLElement | undefined>();
|
||||
|
||||
const showBigPostButton = defaultStore.state.showBigPostButton;
|
||||
|
||||
|
@ -360,6 +380,7 @@ const visibility = ref(
|
|||
: defaultStore.state
|
||||
.defaultNoteVisibility) as (typeof firefish.noteVisibilities)[number]),
|
||||
);
|
||||
|
||||
const visibleUsers = ref([]);
|
||||
if (props.initialVisibleUsers) {
|
||||
props.initialVisibleUsers.forEach(pushVisibleUser);
|
||||
|
@ -581,6 +602,7 @@ function watchForDraft() {
|
|||
watch(files, () => saveDraft(), { deep: true });
|
||||
watch(visibility, () => saveDraft());
|
||||
watch(localOnly, () => saveDraft());
|
||||
watch(language, () => saveDraft());
|
||||
}
|
||||
|
||||
function checkMissingMention() {
|
||||
|
@ -708,6 +730,105 @@ function setVisibility() {
|
|||
);
|
||||
}
|
||||
|
||||
const language = ref<string | null>(
|
||||
props.initialLanguage ??
|
||||
defaultStore.state.recentlyUsedPostLanguages[0] ??
|
||||
localStorage.getItem("lang")?.split("-")[0],
|
||||
);
|
||||
|
||||
function filterLangmapByPrefix(
|
||||
prefix: string,
|
||||
): { langCode: string; nativeName: string }[] {
|
||||
let to_return = Object.entries(langmap)
|
||||
.filter(([langCode, _]) => langCode.startsWith(prefix))
|
||||
.map(([langCode, v]) => {
|
||||
return { langCode, nativeName: v.nativeName };
|
||||
});
|
||||
|
||||
if (prefix === "zh")
|
||||
to_return = to_return.concat([
|
||||
{ langCode: "yue", nativeName: langmap["yue"].nativeName },
|
||||
{ langCode: "nan", nativeName: langmap["nan"].nativeName },
|
||||
]);
|
||||
|
||||
return to_return;
|
||||
}
|
||||
|
||||
function setLanguage() {
|
||||
const actions: Array<MenuItem> = [];
|
||||
|
||||
const detectedLanguage: string = detectLanguage(text.value) ?? "";
|
||||
if (detectedLanguage !== "" && detectedLanguage !== language.value) {
|
||||
actions.push({
|
||||
type: "label",
|
||||
text: i18n.ts.suggested,
|
||||
});
|
||||
filterLangmapByPrefix(detectedLanguage).forEach((v) => {
|
||||
actions.push({
|
||||
text: v.nativeName,
|
||||
danger: false,
|
||||
active: false,
|
||||
action: () => {
|
||||
language.value = v.langCode;
|
||||
},
|
||||
});
|
||||
});
|
||||
actions.push(null);
|
||||
}
|
||||
|
||||
if (language.value != null)
|
||||
actions.push({
|
||||
text: langmap[language.value].nativeName,
|
||||
danger: false,
|
||||
active: true,
|
||||
action: () => {},
|
||||
});
|
||||
|
||||
const langs = Object.keys(langmap);
|
||||
|
||||
// Show recently used language first
|
||||
let recentlyUsedLanguagesExist = false;
|
||||
for (const lang of defaultStore.state.recentlyUsedPostLanguages) {
|
||||
if (lang === language.value) continue;
|
||||
if (!langs.includes(lang)) continue;
|
||||
actions.push({
|
||||
text: langmap[lang].nativeName,
|
||||
danger: false,
|
||||
active: false,
|
||||
action: () => {
|
||||
language.value = lang;
|
||||
},
|
||||
});
|
||||
recentlyUsedLanguagesExist = true;
|
||||
}
|
||||
if (recentlyUsedLanguagesExist) actions.push(null);
|
||||
|
||||
actions.push({
|
||||
text: i18n.ts.noLanguage,
|
||||
danger: false,
|
||||
active: false,
|
||||
action: () => {
|
||||
language.value = null;
|
||||
},
|
||||
});
|
||||
|
||||
for (const lang of langs) {
|
||||
if (lang === language.value) continue;
|
||||
if (defaultStore.state.recentlyUsedPostLanguages.includes(lang))
|
||||
continue;
|
||||
actions.push({
|
||||
text: langmap[lang].nativeName,
|
||||
danger: false,
|
||||
active: false,
|
||||
action: () => {
|
||||
language.value = lang;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
os.popupMenu(actions, languageButton.value, {});
|
||||
}
|
||||
|
||||
function pushVisibleUser(user) {
|
||||
if (
|
||||
!visibleUsers.value.some(
|
||||
|
@ -859,6 +980,7 @@ function saveDraft() {
|
|||
cw: cw.value,
|
||||
visibility: visibility.value,
|
||||
localOnly: localOnly.value,
|
||||
lang: language.value,
|
||||
files: files.value,
|
||||
poll: poll.value,
|
||||
},
|
||||
|
@ -892,6 +1014,7 @@ async function post() {
|
|||
channelId: props.channel ? props.channel.id : undefined,
|
||||
poll: poll.value,
|
||||
cw: useCw.value ? cw.value || "" : undefined,
|
||||
lang: language.value ? language.value : undefined,
|
||||
localOnly: localOnly.value,
|
||||
visibility:
|
||||
visibility.value === "private" ? "specified" : visibility.value,
|
||||
|
@ -961,6 +1084,20 @@ async function post() {
|
|||
});
|
||||
});
|
||||
vibrate([10, 20, 10, 20, 10, 20, 60]);
|
||||
|
||||
// update recentlyUsedLanguages
|
||||
if (language.value != null) {
|
||||
const languages = Object.keys(langmap);
|
||||
const maxLength = 6;
|
||||
|
||||
defaultStore.state.recentlyUsedPostLanguages = [language.value]
|
||||
.concat(
|
||||
defaultStore.state.recentlyUsedPostLanguages.filter((lang) => {
|
||||
return lang !== language.value && languages.includes(lang);
|
||||
}),
|
||||
)
|
||||
.slice(0, maxLength);
|
||||
}
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
|
@ -1047,6 +1184,7 @@ onMounted(() => {
|
|||
cw.value = draft.data.cw;
|
||||
visibility.value = draft.data.visibility;
|
||||
localOnly.value = draft.data.localOnly;
|
||||
language.value = draft.data.lang;
|
||||
files.value = (draft.data.files || []).filter(
|
||||
(draftFile) => draftFile,
|
||||
);
|
||||
|
@ -1073,6 +1211,7 @@ onMounted(() => {
|
|||
}
|
||||
visibility.value = init.visibility;
|
||||
localOnly.value = init.localOnly;
|
||||
language.value = init.lang;
|
||||
quoteId.value = init.renote ? init.renote.id : null;
|
||||
}
|
||||
|
||||
|
@ -1150,6 +1289,11 @@ onMounted(() => {
|
|||
opacity: 0.7;
|
||||
}
|
||||
|
||||
> .language {
|
||||
height: 34px;
|
||||
width: 34px;
|
||||
}
|
||||
|
||||
> .preview {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
|
|
|
@ -33,6 +33,7 @@ const props = defineProps<{
|
|||
specified?: firefish.entities.User;
|
||||
initialText?: string;
|
||||
initialVisibility?: typeof firefish.noteVisibilities;
|
||||
initialLanguage?: typeof firefish.languages;
|
||||
initialFiles?: firefish.entities.DriveFile[];
|
||||
initialLocalOnly?: boolean;
|
||||
initialVisibleUsers?: firefish.entities.User[];
|
||||
|
|
|
@ -10,7 +10,7 @@ export const apiUrl = `${url}/api`;
|
|||
export const wsUrl = `${url
|
||||
.replace("http://", "ws://")
|
||||
.replace("https://", "wss://")}/streaming`;
|
||||
export const lang = localStorage.getItem("lang");
|
||||
export const lang = localStorage.getItem("lang")?.split("-")[0] ?? "en";
|
||||
export const langs = _LANGS_;
|
||||
export const locale = JSON.parse(localStorage.getItem("locale") || "en-US");
|
||||
export const version = _VERSION_;
|
||||
|
|
|
@ -124,7 +124,7 @@ function checkForSplash() {
|
|||
// #region Set lang attr
|
||||
const html = document.documentElement;
|
||||
html.setAttribute("lang", lang || "en-US");
|
||||
html.setAttribute("dir", langmap[lang].rtl ? "rtl" : "ltr");
|
||||
html.setAttribute("dir", langmap[lang].rtl === true ? "rtl" : "ltr");
|
||||
//#endregion
|
||||
|
||||
// #region loginId
|
||||
|
|
|
@ -1,20 +1,7 @@
|
|||
// TODO: sharedに置いてバックエンドのと統合したい
|
||||
export const langmap = {
|
||||
ach: {
|
||||
nativeName: "Lwo",
|
||||
},
|
||||
ady: {
|
||||
nativeName: "Адыгэбзэ",
|
||||
},
|
||||
export const iso639Langs1 = {
|
||||
af: {
|
||||
nativeName: "Afrikaans",
|
||||
},
|
||||
"af-NA": {
|
||||
nativeName: "Afrikaans (Namibia)",
|
||||
},
|
||||
"af-ZA": {
|
||||
nativeName: "Afrikaans (South Africa)",
|
||||
},
|
||||
ak: {
|
||||
nativeName: "Tɕɥi",
|
||||
},
|
||||
|
@ -22,359 +9,150 @@ export const langmap = {
|
|||
nativeName: "العربية",
|
||||
rtl: true,
|
||||
},
|
||||
"ar-AR": {
|
||||
nativeName: "العربية",
|
||||
rtl: true,
|
||||
},
|
||||
"ar-MA": {
|
||||
nativeName: "العربية",
|
||||
rtl: true,
|
||||
},
|
||||
"ar-SA": {
|
||||
nativeName: "العربية (السعودية)",
|
||||
rtl: true,
|
||||
},
|
||||
"ay-BO": {
|
||||
ay: {
|
||||
nativeName: "Aymar aru",
|
||||
},
|
||||
az: {
|
||||
nativeName: "Azərbaycan dili",
|
||||
},
|
||||
"az-AZ": {
|
||||
nativeName: "Azərbaycan dili",
|
||||
},
|
||||
"be-BY": {
|
||||
be: {
|
||||
nativeName: "Беларуская",
|
||||
},
|
||||
bg: {
|
||||
nativeName: "Български",
|
||||
},
|
||||
"bg-BG": {
|
||||
nativeName: "Български",
|
||||
},
|
||||
bn: {
|
||||
nativeName: "বাংলা",
|
||||
},
|
||||
"bn-IN": {
|
||||
nativeName: "বাংলা (ভারত)",
|
||||
},
|
||||
"bn-BD": {
|
||||
nativeName: "বাংলা(বাংলাদেশ)",
|
||||
},
|
||||
br: {
|
||||
nativeName: "Brezhoneg",
|
||||
},
|
||||
"bs-BA": {
|
||||
bs: {
|
||||
nativeName: "Bosanski",
|
||||
},
|
||||
ca: {
|
||||
nativeName: "Català",
|
||||
},
|
||||
"ca-ES": {
|
||||
nativeName: "Català",
|
||||
},
|
||||
cak: {
|
||||
nativeName: "Maya Kaqchikel",
|
||||
},
|
||||
"ck-US": {
|
||||
nativeName: "ᏣᎳᎩ (tsalagi)",
|
||||
},
|
||||
cs: {
|
||||
nativeName: "Čeština",
|
||||
},
|
||||
"cs-CZ": {
|
||||
nativeName: "Čeština",
|
||||
},
|
||||
cy: {
|
||||
nativeName: "Cymraeg",
|
||||
},
|
||||
"cy-GB": {
|
||||
nativeName: "Cymraeg",
|
||||
},
|
||||
da: {
|
||||
nativeName: "Dansk",
|
||||
},
|
||||
"da-DK": {
|
||||
nativeName: "Dansk",
|
||||
},
|
||||
de: {
|
||||
nativeName: "Deutsch",
|
||||
},
|
||||
"de-AT": {
|
||||
nativeName: "Deutsch (Österreich)",
|
||||
},
|
||||
"de-DE": {
|
||||
nativeName: "Deutsch (Deutschland)",
|
||||
},
|
||||
"de-CH": {
|
||||
nativeName: "Deutsch (Schweiz)",
|
||||
},
|
||||
dsb: {
|
||||
nativeName: "Dolnoserbšćina",
|
||||
},
|
||||
el: {
|
||||
nativeName: "Ελληνικά",
|
||||
},
|
||||
"el-GR": {
|
||||
nativeName: "Ελληνικά",
|
||||
},
|
||||
en: {
|
||||
nativeName: "English",
|
||||
},
|
||||
"en-GB": {
|
||||
nativeName: "English (UK)",
|
||||
},
|
||||
"en-AU": {
|
||||
nativeName: "English (Australia)",
|
||||
},
|
||||
"en-CA": {
|
||||
nativeName: "English (Canada)",
|
||||
},
|
||||
"en-IE": {
|
||||
nativeName: "English (Ireland)",
|
||||
},
|
||||
"en-IN": {
|
||||
nativeName: "English (India)",
|
||||
},
|
||||
"en-PI": {
|
||||
nativeName: "English (Pirate)",
|
||||
},
|
||||
"en-SG": {
|
||||
nativeName: "English (Singapore)",
|
||||
},
|
||||
"en-UD": {
|
||||
nativeName: "English (Upside Down)",
|
||||
},
|
||||
"en-US": {
|
||||
nativeName: "English (US)",
|
||||
},
|
||||
"en-ZA": {
|
||||
nativeName: "English (South Africa)",
|
||||
},
|
||||
"en@pirate": {
|
||||
nativeName: "English (Pirate)",
|
||||
},
|
||||
eo: {
|
||||
nativeName: "Esperanto",
|
||||
},
|
||||
"eo-EO": {
|
||||
nativeName: "Esperanto",
|
||||
},
|
||||
es: {
|
||||
nativeName: "Español",
|
||||
},
|
||||
"es-AR": {
|
||||
nativeName: "Español (Argentine)",
|
||||
},
|
||||
"es-419": {
|
||||
nativeName: "Español (Latinoamérica)",
|
||||
},
|
||||
"es-CL": {
|
||||
nativeName: "Español (Chile)",
|
||||
},
|
||||
"es-CO": {
|
||||
nativeName: "Español (Colombia)",
|
||||
},
|
||||
"es-EC": {
|
||||
nativeName: "Español (Ecuador)",
|
||||
},
|
||||
"es-ES": {
|
||||
nativeName: "Español (España)",
|
||||
},
|
||||
"es-LA": {
|
||||
nativeName: "Español (Latinoamérica)",
|
||||
},
|
||||
"es-NI": {
|
||||
nativeName: "Español (Nicaragua)",
|
||||
},
|
||||
"es-MX": {
|
||||
nativeName: "Español (México)",
|
||||
},
|
||||
"es-US": {
|
||||
nativeName: "Español (Estados Unidos)",
|
||||
},
|
||||
"es-VE": {
|
||||
nativeName: "Español (Venezuela)",
|
||||
},
|
||||
et: {
|
||||
nativeName: "eesti keel",
|
||||
},
|
||||
"et-EE": {
|
||||
nativeName: "Eesti (Estonia)",
|
||||
},
|
||||
eu: {
|
||||
nativeName: "Euskara",
|
||||
},
|
||||
"eu-ES": {
|
||||
nativeName: "Euskara",
|
||||
},
|
||||
fa: {
|
||||
nativeName: "فارسی",
|
||||
rtl: true,
|
||||
},
|
||||
"fa-IR": {
|
||||
nativeName: "فارسی",
|
||||
rtl: true,
|
||||
},
|
||||
"fb-LT": {
|
||||
nativeName: "Leet Speak",
|
||||
},
|
||||
ff: {
|
||||
nativeName: "Fulah",
|
||||
},
|
||||
fi: {
|
||||
nativeName: "Suomi",
|
||||
},
|
||||
"fi-FI": {
|
||||
nativeName: "Suomi",
|
||||
},
|
||||
fo: {
|
||||
nativeName: "Føroyskt",
|
||||
},
|
||||
"fo-FO": {
|
||||
nativeName: "Føroyskt (Færeyjar)",
|
||||
},
|
||||
fr: {
|
||||
nativeName: "Français",
|
||||
},
|
||||
"fr-CA": {
|
||||
nativeName: "Français (Canada)",
|
||||
},
|
||||
"fr-FR": {
|
||||
nativeName: "Français (France)",
|
||||
},
|
||||
"fr-BE": {
|
||||
nativeName: "Français (Belgique)",
|
||||
},
|
||||
"fr-CH": {
|
||||
nativeName: "Français (Suisse)",
|
||||
},
|
||||
"fy-NL": {
|
||||
fy: {
|
||||
nativeName: "Frysk",
|
||||
},
|
||||
ga: {
|
||||
nativeName: "Gaeilge",
|
||||
},
|
||||
"ga-IE": {
|
||||
nativeName: "Gaeilge",
|
||||
},
|
||||
gd: {
|
||||
nativeName: "Gàidhlig",
|
||||
},
|
||||
gl: {
|
||||
nativeName: "Galego",
|
||||
},
|
||||
"gl-ES": {
|
||||
nativeName: "Galego",
|
||||
},
|
||||
"gn-PY": {
|
||||
gn: {
|
||||
nativeName: "Avañe'ẽ",
|
||||
},
|
||||
"gu-IN": {
|
||||
gu: {
|
||||
nativeName: "ગુજરાતી",
|
||||
},
|
||||
gv: {
|
||||
nativeName: "Gaelg",
|
||||
},
|
||||
"gx-GR": {
|
||||
nativeName: "Ἑλληνική ἀρχαία",
|
||||
},
|
||||
he: {
|
||||
nativeName: "עברית",
|
||||
rtl: true,
|
||||
},
|
||||
"he-IL": {
|
||||
nativeName: "עברית",
|
||||
rtl: true,
|
||||
},
|
||||
hi: {
|
||||
nativeName: "हिन्दी",
|
||||
},
|
||||
"hi-IN": {
|
||||
nativeName: "हिन्दी",
|
||||
},
|
||||
hr: {
|
||||
nativeName: "Hrvatski",
|
||||
},
|
||||
"hr-HR": {
|
||||
nativeName: "Hrvatski",
|
||||
},
|
||||
hsb: {
|
||||
nativeName: "Hornjoserbšćina",
|
||||
},
|
||||
ht: {
|
||||
nativeName: "Kreyòl",
|
||||
},
|
||||
hu: {
|
||||
nativeName: "Magyar",
|
||||
},
|
||||
"hu-HU": {
|
||||
nativeName: "Magyar",
|
||||
},
|
||||
hy: {
|
||||
nativeName: "Հայերեն",
|
||||
},
|
||||
"hy-AM": {
|
||||
nativeName: "Հայերեն (Հայաստան)",
|
||||
},
|
||||
id: {
|
||||
nativeName: "Bahasa Indonesia",
|
||||
},
|
||||
"id-ID": {
|
||||
nativeName: "Bahasa Indonesia",
|
||||
},
|
||||
is: {
|
||||
nativeName: "Íslenska",
|
||||
},
|
||||
"is-IS": {
|
||||
nativeName: "Íslenska (Iceland)",
|
||||
},
|
||||
it: {
|
||||
nativeName: "Italiano",
|
||||
},
|
||||
"it-IT": {
|
||||
nativeName: "Italiano",
|
||||
},
|
||||
ja: {
|
||||
nativeName: "日本語",
|
||||
},
|
||||
"ja-JP": {
|
||||
nativeName: "日本語 (日本)",
|
||||
},
|
||||
"jv-ID": {
|
||||
jv: {
|
||||
nativeName: "Basa Jawa",
|
||||
},
|
||||
"ka-GE": {
|
||||
ka: {
|
||||
nativeName: "ქართული",
|
||||
},
|
||||
"kk-KZ": {
|
||||
kk: {
|
||||
nativeName: "Қазақша",
|
||||
},
|
||||
km: {
|
||||
nativeName: "ភាសាខ្មែរ",
|
||||
},
|
||||
kl: {
|
||||
nativeName: "kalaallisut",
|
||||
},
|
||||
"km-KH": {
|
||||
km: {
|
||||
nativeName: "ភាសាខ្មែរ",
|
||||
},
|
||||
kab: {
|
||||
nativeName: "Taqbaylit",
|
||||
},
|
||||
kn: {
|
||||
nativeName: "ಕನ್ನಡ",
|
||||
},
|
||||
"kn-IN": {
|
||||
nativeName: "ಕನ್ನಡ (India)",
|
||||
},
|
||||
ko: {
|
||||
nativeName: "한국어",
|
||||
},
|
||||
"ko-KR": {
|
||||
nativeName: "한국어 (한국)",
|
||||
},
|
||||
"ku-TR": {
|
||||
ku: {
|
||||
nativeName: "Kurdî",
|
||||
},
|
||||
kw: {
|
||||
|
@ -383,66 +161,39 @@ export const langmap = {
|
|||
la: {
|
||||
nativeName: "Latin",
|
||||
},
|
||||
"la-VA": {
|
||||
nativeName: "Latin",
|
||||
},
|
||||
lb: {
|
||||
nativeName: "Lëtzebuergesch",
|
||||
},
|
||||
"li-NL": {
|
||||
li: {
|
||||
nativeName: "Lèmbörgs",
|
||||
},
|
||||
lt: {
|
||||
nativeName: "Lietuvių",
|
||||
},
|
||||
"lt-LT": {
|
||||
nativeName: "Lietuvių",
|
||||
},
|
||||
lv: {
|
||||
nativeName: "Latviešu",
|
||||
},
|
||||
"lv-LV": {
|
||||
nativeName: "Latviešu",
|
||||
},
|
||||
mai: {
|
||||
nativeName: "मैथिली, মৈথিলী",
|
||||
},
|
||||
"mg-MG": {
|
||||
mg: {
|
||||
nativeName: "Malagasy",
|
||||
},
|
||||
mk: {
|
||||
nativeName: "Македонски",
|
||||
},
|
||||
"mk-MK": {
|
||||
nativeName: "Македонски (Македонски)",
|
||||
},
|
||||
ml: {
|
||||
nativeName: "മലയാളം",
|
||||
},
|
||||
"ml-IN": {
|
||||
nativeName: "മലയാളം",
|
||||
},
|
||||
"mn-MN": {
|
||||
mn: {
|
||||
nativeName: "Монгол",
|
||||
},
|
||||
mr: {
|
||||
nativeName: "मराठी",
|
||||
},
|
||||
"mr-IN": {
|
||||
nativeName: "मराठी",
|
||||
},
|
||||
ms: {
|
||||
nativeName: "Bahasa Melayu",
|
||||
},
|
||||
"ms-MY": {
|
||||
nativeName: "Bahasa Melayu",
|
||||
},
|
||||
mt: {
|
||||
nativeName: "Malti",
|
||||
},
|
||||
"mt-MT": {
|
||||
nativeName: "Malti",
|
||||
},
|
||||
my: {
|
||||
nativeName: "ဗမာစကာ",
|
||||
},
|
||||
|
@ -452,228 +203,179 @@ export const langmap = {
|
|||
nb: {
|
||||
nativeName: "Norsk (bokmål)",
|
||||
},
|
||||
"nb-NO": {
|
||||
nativeName: "Norsk (bokmål)",
|
||||
},
|
||||
ne: {
|
||||
nativeName: "नेपाली",
|
||||
},
|
||||
"ne-NP": {
|
||||
nativeName: "नेपाली",
|
||||
},
|
||||
nl: {
|
||||
nativeName: "Nederlands",
|
||||
},
|
||||
"nl-BE": {
|
||||
nativeName: "Nederlands (België)",
|
||||
},
|
||||
"nl-NL": {
|
||||
nativeName: "Nederlands (Nederland)",
|
||||
},
|
||||
"nn-NO": {
|
||||
nn: {
|
||||
nativeName: "Norsk (nynorsk)",
|
||||
},
|
||||
oc: {
|
||||
nativeName: "Occitan",
|
||||
},
|
||||
"or-IN": {
|
||||
or: {
|
||||
nativeName: "ଓଡ଼ିଆ",
|
||||
},
|
||||
pa: {
|
||||
nativeName: "ਪੰਜਾਬੀ",
|
||||
},
|
||||
"pa-IN": {
|
||||
nativeName: "ਪੰਜਾਬੀ (ਭਾਰਤ ਨੂੰ)",
|
||||
},
|
||||
pl: {
|
||||
nativeName: "Polski",
|
||||
},
|
||||
"pl-PL": {
|
||||
nativeName: "Polski",
|
||||
},
|
||||
"ps-AF": {
|
||||
ps: {
|
||||
nativeName: "پښتو",
|
||||
rtl: true,
|
||||
},
|
||||
pt: {
|
||||
nativeName: "Português",
|
||||
},
|
||||
"pt-BR": {
|
||||
nativeName: "Português (Brasil)",
|
||||
},
|
||||
"pt-PT": {
|
||||
nativeName: "Português (Portugal)",
|
||||
},
|
||||
"qu-PE": {
|
||||
qu: {
|
||||
nativeName: "Qhichwa",
|
||||
},
|
||||
"rm-CH": {
|
||||
rm: {
|
||||
nativeName: "Rumantsch",
|
||||
},
|
||||
ro: {
|
||||
nativeName: "Română",
|
||||
},
|
||||
"ro-RO": {
|
||||
nativeName: "Română",
|
||||
},
|
||||
ru: {
|
||||
nativeName: "Русский",
|
||||
},
|
||||
"ru-RU": {
|
||||
nativeName: "Русский",
|
||||
},
|
||||
"sa-IN": {
|
||||
sa: {
|
||||
nativeName: "संस्कृतम्",
|
||||
},
|
||||
"se-NO": {
|
||||
se: {
|
||||
nativeName: "Davvisámegiella",
|
||||
},
|
||||
sh: {
|
||||
nativeName: "српскохрватски",
|
||||
},
|
||||
"si-LK": {
|
||||
si: {
|
||||
nativeName: "සිංහල",
|
||||
},
|
||||
sk: {
|
||||
nativeName: "Slovenčina",
|
||||
},
|
||||
"sk-SK": {
|
||||
nativeName: "Slovenčina (Slovakia)",
|
||||
},
|
||||
sl: {
|
||||
nativeName: "Slovenščina",
|
||||
},
|
||||
"sl-SI": {
|
||||
nativeName: "Slovenščina",
|
||||
},
|
||||
"so-SO": {
|
||||
so: {
|
||||
nativeName: "Soomaaliga",
|
||||
},
|
||||
sq: {
|
||||
nativeName: "Shqip",
|
||||
},
|
||||
"sq-AL": {
|
||||
nativeName: "Shqip",
|
||||
},
|
||||
sr: {
|
||||
nativeName: "Српски",
|
||||
},
|
||||
"sr-RS": {
|
||||
nativeName: "Српски (Serbia)",
|
||||
},
|
||||
su: {
|
||||
nativeName: "Basa Sunda",
|
||||
},
|
||||
sv: {
|
||||
nativeName: "Svenska",
|
||||
},
|
||||
"sv-SE": {
|
||||
nativeName: "Svenska",
|
||||
},
|
||||
sw: {
|
||||
nativeName: "Kiswahili",
|
||||
},
|
||||
"sw-KE": {
|
||||
nativeName: "Kiswahili",
|
||||
},
|
||||
ta: {
|
||||
nativeName: "தமிழ்",
|
||||
},
|
||||
"ta-IN": {
|
||||
nativeName: "தமிழ்",
|
||||
},
|
||||
te: {
|
||||
nativeName: "తెలుగు",
|
||||
},
|
||||
"te-IN": {
|
||||
nativeName: "తెలుగు",
|
||||
},
|
||||
tg: {
|
||||
nativeName: "забо́ни тоҷикӣ́",
|
||||
},
|
||||
"tg-TJ": {
|
||||
nativeName: "тоҷикӣ",
|
||||
},
|
||||
th: {
|
||||
nativeName: "ภาษาไทย",
|
||||
},
|
||||
"th-TH": {
|
||||
nativeName: "ภาษาไทย (ประเทศไทย)",
|
||||
},
|
||||
fil: {
|
||||
nativeName: "Filipino",
|
||||
},
|
||||
tlh: {
|
||||
nativeName: "tlhIngan-Hol",
|
||||
},
|
||||
tr: {
|
||||
nativeName: "Türkçe",
|
||||
},
|
||||
"tr-TR": {
|
||||
nativeName: "Türkçe",
|
||||
},
|
||||
"tt-RU": {
|
||||
tt: {
|
||||
nativeName: "татарча",
|
||||
},
|
||||
uk: {
|
||||
nativeName: "Українська",
|
||||
},
|
||||
"uk-UA": {
|
||||
nativeName: "Українська",
|
||||
},
|
||||
ur: {
|
||||
nativeName: "اردو",
|
||||
rtl: true,
|
||||
},
|
||||
"ur-PK": {
|
||||
nativeName: "اردو",
|
||||
rtl: true,
|
||||
},
|
||||
uz: {
|
||||
nativeName: "O'zbek",
|
||||
},
|
||||
"uz-UZ": {
|
||||
nativeName: "O'zbek",
|
||||
},
|
||||
vi: {
|
||||
nativeName: "Tiếng Việt",
|
||||
},
|
||||
"vi-VN": {
|
||||
nativeName: "Tiếng Việt",
|
||||
},
|
||||
"xh-ZA": {
|
||||
xh: {
|
||||
nativeName: "isiXhosa",
|
||||
},
|
||||
yi: {
|
||||
nativeName: "ייִדיש",
|
||||
rtl: true,
|
||||
},
|
||||
"yi-DE": {
|
||||
nativeName: "ייִדיש (German)",
|
||||
rtl: true,
|
||||
},
|
||||
zh: {
|
||||
nativeName: "中文",
|
||||
},
|
||||
"zh-Hans": {
|
||||
nativeName: "中文简体",
|
||||
},
|
||||
"zh-Hant": {
|
||||
nativeName: "中文繁體",
|
||||
},
|
||||
"zh-CN": {
|
||||
nativeName: "中文(中国大陆)",
|
||||
},
|
||||
"zh-HK": {
|
||||
nativeName: "中文(香港)",
|
||||
},
|
||||
"zh-SG": {
|
||||
nativeName: "中文(新加坡)",
|
||||
},
|
||||
"zh-TW": {
|
||||
nativeName: "中文(台灣)",
|
||||
},
|
||||
"zu-ZA": {
|
||||
zu: {
|
||||
nativeName: "isiZulu",
|
||||
},
|
||||
};
|
||||
|
||||
export const iso639Langs3 = {
|
||||
ach: {
|
||||
nativeName: "Lwo",
|
||||
},
|
||||
ady: {
|
||||
nativeName: "Адыгэбзэ",
|
||||
},
|
||||
cak: {
|
||||
nativeName: "Maya Kaqchikel",
|
||||
},
|
||||
chr: {
|
||||
nativeName: "ᏣᎳᎩ (tsalagi)",
|
||||
},
|
||||
dsb: {
|
||||
nativeName: "Dolnoserbšćina",
|
||||
},
|
||||
fil: {
|
||||
nativeName: "Filipino",
|
||||
},
|
||||
hsb: {
|
||||
nativeName: "Hornjoserbšćina",
|
||||
},
|
||||
kab: {
|
||||
nativeName: "Taqbaylit",
|
||||
},
|
||||
mai: {
|
||||
nativeName: "मैथिली, মৈথিলী",
|
||||
},
|
||||
tlh: {
|
||||
nativeName: "tlhIngan-Hol",
|
||||
},
|
||||
tok: {
|
||||
nativeName: "Toki Pona",
|
||||
},
|
||||
yue: {
|
||||
nativeName: "粵語",
|
||||
},
|
||||
nan: {
|
||||
nativeName: "閩南語",
|
||||
},
|
||||
};
|
||||
|
||||
export const langmapNoRegion = Object.assign({}, iso639Langs1, iso639Langs3);
|
||||
|
||||
export const iso639Regional = {
|
||||
"zh-hans": {
|
||||
nativeName: "中文(简体)",
|
||||
},
|
||||
"zh-hant": {
|
||||
nativeName: "中文(繁體)",
|
||||
},
|
||||
};
|
||||
|
||||
export const langmap = Object.assign({}, langmapNoRegion, iso639Regional);
|
||||
|
|
|
@ -430,6 +430,10 @@ export const defaultStore = markRaw(
|
|||
where: "device",
|
||||
default: 140,
|
||||
},
|
||||
recentlyUsedPostLanguages: {
|
||||
where: "account",
|
||||
default: [] as string[],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
|
|
|
@ -58,3 +58,96 @@ export const permissions = [
|
|||
"read:gallery-likes",
|
||||
"write:gallery-likes",
|
||||
];
|
||||
|
||||
export const languages = [
|
||||
"ach",
|
||||
"ady",
|
||||
"af",
|
||||
"ak",
|
||||
"ar",
|
||||
"az",
|
||||
"bg",
|
||||
"bn",
|
||||
"br",
|
||||
"ca",
|
||||
"cak",
|
||||
"cs",
|
||||
"cy",
|
||||
"da",
|
||||
"de",
|
||||
"dsb",
|
||||
"el",
|
||||
"en",
|
||||
"eo",
|
||||
"es",
|
||||
"et",
|
||||
"eu",
|
||||
"fa",
|
||||
"ff",
|
||||
"fi",
|
||||
"fo",
|
||||
"fr",
|
||||
"ga",
|
||||
"gd",
|
||||
"gl",
|
||||
"gv",
|
||||
"he",
|
||||
"hi",
|
||||
"hr",
|
||||
"hsb",
|
||||
"ht",
|
||||
"hu",
|
||||
"hy",
|
||||
"id",
|
||||
"is",
|
||||
"it",
|
||||
"ja",
|
||||
"km",
|
||||
"kl",
|
||||
"kab",
|
||||
"kn",
|
||||
"ko",
|
||||
"kw",
|
||||
"la",
|
||||
"lb",
|
||||
"lt",
|
||||
"lv",
|
||||
"mai",
|
||||
"mk",
|
||||
"ml",
|
||||
"mr",
|
||||
"ms",
|
||||
"mt",
|
||||
"my",
|
||||
"no",
|
||||
"nb",
|
||||
"ne",
|
||||
"nl",
|
||||
"oc",
|
||||
"pa",
|
||||
"pl",
|
||||
"pt",
|
||||
"ro",
|
||||
"ru",
|
||||
"sh",
|
||||
"sk",
|
||||
"sl",
|
||||
"sq",
|
||||
"sr",
|
||||
"su",
|
||||
"sv",
|
||||
"sw",
|
||||
"ta",
|
||||
"te",
|
||||
"tg",
|
||||
"th",
|
||||
"fil",
|
||||
"tlh",
|
||||
"tr",
|
||||
"uk",
|
||||
"ur",
|
||||
"uz",
|
||||
"vi",
|
||||
"yi",
|
||||
"zh",
|
||||
] as const;
|
||||
|
|
|
@ -10,6 +10,7 @@ export const permissions = consts.permissions;
|
|||
export const notificationTypes = consts.notificationTypes;
|
||||
export const noteVisibilities = consts.noteVisibilities;
|
||||
export const mutedNoteReasons = consts.mutedNoteReasons;
|
||||
export const languages = consts.languages;
|
||||
export const ffVisibility = consts.ffVisibility;
|
||||
|
||||
// api extractor not supported yet
|
||||
|
|
Loading…
Reference in a new issue