diff --git a/README.md b/README.md index 1ac4ff602..1ac950010 100644 --- a/README.md +++ b/README.md @@ -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 のコードに入るコメントアートを削除 diff --git a/locales/en-US.yml b/locales/en-US.yml index f1ca55800..40a273837 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -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 diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index d2f33c10c..01a9614da 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -2032,6 +2032,8 @@ _iconSets: regular: "標準" fill: "塗りつぶし" duotone: "2色" +suggested: "候補" +noLanguage: "言語なし" moreUrls: "固定するページ" moreUrlsDescription: "左下のヘルプメニューに固定したいページを以下の形式で、改行区切りで入力してください:\n\"表示名\": https://example.com/" releaseToReload: "離して再読み込み" diff --git a/neko/pnpm-lock.yaml b/neko/pnpm-lock.yaml index 3655bfbf0..858de71fa 100644 --- a/neko/pnpm-lock.yaml +++ b/neko/pnpm-lock.yaml @@ -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==} diff --git a/packages/backend/package.json b/packages/backend/package.json index d8e6bb2f6..fa6833088 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -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", diff --git a/packages/backend/src/misc/detect-language.ts b/packages/backend/src/misc/detect-language.ts deleted file mode 100644 index 6147247de..000000000 --- a/packages/backend/src/misc/detect-language.ts +++ /dev/null @@ -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); -} diff --git a/packages/backend/src/misc/langmap.ts b/packages/backend/src/misc/langmap.ts index 106130d3c..c4d4f0beb 100644 --- a/packages/backend/src/misc/langmap.ts +++ b/packages/backend/src/misc/langmap.ts @@ -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); diff --git a/packages/backend/src/models/schema/note.ts b/packages/backend/src/models/schema/note.ts index e17f054e8..7dcdbc9b0 100644 --- a/packages/backend/src/models/schema/note.ts +++ b/packages/backend/src/models/schema/note.ts @@ -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, diff --git a/packages/backend/src/remote/activitypub/models/note.ts b/packages/backend/src/remote/activitypub/models/note.ts index 575b19fb8..4b05ef7f7 100644 --- a/packages/backend/src/remote/activitypub/models/note.ts +++ b/packages/backend/src/remote/activitypub/models/note.ts @@ -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); diff --git a/packages/backend/src/remote/activitypub/renderer/note.ts b/packages/backend/src/remote/activitypub/renderer/note.ts index c1beb7604..ffa4b2f37 100644 --- a/packages/backend/src/remote/activitypub/renderer/note.ts +++ b/packages/backend/src/remote/activitypub/renderer/note.ts @@ -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; diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index 082108383..7b900a74a 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -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 }, diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts index 0465d09ec..7a4171dc5 100644 --- a/packages/backend/src/server/api/endpoints/notes/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/create.ts @@ -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 }, diff --git a/packages/backend/src/server/api/endpoints/notes/edit.ts b/packages/backend/src/server/api/endpoints/notes/edit.ts index a0869e410..fdb6ede38 100644 --- a/packages/backend/src/server/api/endpoints/notes/edit.ts +++ b/packages/backend/src/server/api/endpoints/notes/edit.ts @@ -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; } diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts index ecf588cdc..1bc99d71f 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -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; } diff --git a/packages/client/src/components/MkPostForm.vue b/packages/client/src/components/MkPostForm.vue index 917eee7ea..65528e248 100644 --- a/packages/client/src/components/MkPostForm.vue +++ b/packages/client/src/components/MkPostForm.vue @@ -54,6 +54,21 @@ > +