feat: Add langPref config option

This commit is contained in:
Essem 2024-02-03 16:45:38 -06:00
parent 4f45e72799
commit 8a416cd302
No known key found for this signature in database
GPG key ID: 7D497397CC3A2A8C
13 changed files with 78 additions and 40 deletions

View file

@ -212,5 +212,9 @@ checkActivityPubGetSignature: false
#customMOTD: ['Hello World', 'The sharks rule all', 'Shonks']
# Prefer these languages for remote notes with language-specific content
# Must be valid language codes according to BCP 47
#langPref: ['en', 'ja']
# Upload or download file size limits (bytes)
#maxFileSize: 262144000

View file

@ -269,5 +269,9 @@ checkActivityPubGetSignature: false
#customMOTD: ['Hello World', 'The sharks rule all', 'Shonks']
# Prefer these languages for remote notes with language-specific content
# Must be valid language codes according to BCP 47
#langPref: ['en', 'ja']
# Upload or download file size limits (bytes)
#maxFileSize: 262144000

View file

@ -284,6 +284,10 @@ checkActivityPubGetSignature: false
#customMOTD: ['Hello World', 'The sharks rule all', 'Shonks']
# Prefer these languages for remote notes with language-specific content
# Must be valid language codes according to BCP 47
#langPref: ['en', 'ja']
# Upload or download file size limits (bytes)
#maxFileSize: 262144000

View file

@ -91,6 +91,8 @@ type Source = {
customMOTD?: string[];
langPref?: string[];
signToActivityPubGet?: boolean;
checkActivityPubGetSignature?: boolean;
@ -153,6 +155,7 @@ export type Config = {
customMOTD: string[] | undefined;
signToActivityPubGet: boolean;
checkActivityPubGetSignature: boolean | undefined;
langPref: string[];
version: string;
publishTarballInsteadOfProvideRepositoryUrl: boolean;
@ -269,6 +272,7 @@ export function loadConfig(): Config {
inboxJobMaxAttempts: config.inboxJobMaxAttempts,
proxyRemoteFiles: config.proxyRemoteFiles,
customMOTD: config.customMOTD,
langPref: config.langPref ?? ['en', 'ja'],
signToActivityPubGet: config.signToActivityPubGet ?? true,
checkActivityPubGetSignature: config.checkActivityPubGetSignature,
mediaProxy: externalMediaProxy ?? internalMediaProxy,

View file

@ -25,7 +25,7 @@ import { StatusError } from '@/misc/status-error.js';
import { UtilityService } from '@/core/UtilityService.js';
import { bindThis } from '@/decorators.js';
import { checkHttps } from '@/misc/check-https.js';
import { langmap } from '@/misc/langmap.js';
import { langs } from '@/misc/langmap.js';
import { getOneApId, getApId, getOneApHrefNullable, validPost, isEmoji, getApType } from '../type.js';
import { ApLoggerService } from '../ApLoggerService.js';
import { ApMfmService } from '../ApMfmService.js';
@ -241,25 +241,37 @@ export class ApNoteService {
const cw = note.summary === '' ? null : note.summary;
let lang: string | null = null;
if (note.contentMap != null) {
for (const preferredLang of this.config.langPref) {
if (note.contentMap[preferredLang]) {
lang = preferredLang;
break;
}
}
if (!lang) lang = Object.keys(note.contentMap)[0];
if (!langs.includes(lang)) lang = null;
}
// テキストのパース
let text: string | null = null;
if (note.source?.mediaType === 'text/x.misskeymarkdown' && typeof note.source.content === 'string') {
text = note.source.content;
} else if (note.contentMap != null) {
const entry = Object.entries(note.contentMap)[0];
text = this.apMfmService.htmlToMfm(entry[1], note.tag);
} else if (note.contentMap != null && Object.keys(note.contentMap).length !== 0) {
let content: string;
if (lang) {
content = note.contentMap[lang];
} else {
content = Object.values(note.contentMap)[0];
}
text = this.apMfmService.htmlToMfm(content, note.tag);
} else if (typeof note._misskey_content !== 'undefined') {
text = note._misskey_content;
} else if (typeof note.content === 'string') {
text = this.apMfmService.htmlToMfm(note.content, note.tag);
}
let lang: string | null = null;
if (note.contentMap != null) {
const key = Object.keys(note.contentMap)[0];
lang = Object.keys(langmap).includes(key) ? key : null;
}
// vote
if (reply && reply.hasPoll) {
const poll = await this.pollsRepository.findOneByOrFail({ noteId: reply.id });
@ -459,25 +471,37 @@ export class ApNoteService {
const cw = note.summary === '' ? null : note.summary;
let lang: string | null = null;
if (note.contentMap != null) {
for (const preferredLang of this.config.langPref) {
if (note.contentMap[preferredLang]) {
lang = preferredLang;
break;
}
}
if (!lang) lang = Object.keys(note.contentMap)[0];
if (!langs.includes(lang)) lang = null;
}
// テキストのパース
let text: string | null = null;
if (note.source?.mediaType === 'text/x.misskeymarkdown' && typeof note.source.content === 'string') {
text = note.source.content;
} else if (note.contentMap != null) {
const entry = Object.entries(note.contentMap)[0];
text = this.apMfmService.htmlToMfm(entry[1], note.tag);
} else if (note.contentMap != null && Object.keys(note.contentMap).length !== 0) {
let content: string;
if (lang) {
content = note.contentMap[lang];
} else {
content = Object.values(note.contentMap)[0];
}
text = this.apMfmService.htmlToMfm(content, note.tag);
} else if (typeof note._misskey_content !== 'undefined') {
text = note._misskey_content;
} else if (typeof note.content === 'string') {
text = this.apMfmService.htmlToMfm(note.content, note.tag);
}
let lang: string | null = null;
if (note.contentMap != null) {
const key = Object.keys(note.contentMap)[0];
lang = Object.keys(langmap).includes(key) ? key : null;
}
// vote
if (reply && reply.hasPoll) {
const poll = await this.pollsRepository.findOneByOrFail({ noteId: reply.id });

View file

@ -385,3 +385,4 @@ export const iso639Regional = {
};
export const langmap = Object.assign({}, langmapNoRegion, iso639Regional);
export const langs = Object.keys(langmap);

View file

@ -2,7 +2,7 @@
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { langmap } from '@/misc/langmap.js';
import { langs } from '@/misc/langmap.js';
export const packedNoteSchema = {
type: 'object',
@ -29,7 +29,7 @@ export const packedNoteSchema = {
},
lang: {
type: 'string',
enum: [...Object.keys(langmap)],
enum: langs,
nullable: true,
},
cw: {

View file

@ -17,7 +17,7 @@ import { birthdaySchema, listenbrainzSchema, descriptionSchema, locationSchema,
import type { MiUserProfile } from '@/models/UserProfile.js';
import { notificationTypes } from '@/types.js';
import { normalizeForSearch } from '@/misc/normalize-for-search.js';
import { langmap } from '@/misc/langmap.js';
import { langs } from '@/misc/langmap.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
@ -149,7 +149,7 @@ export const paramDef = {
location: { ...locationSchema, nullable: true },
birthday: { ...birthdaySchema, nullable: true },
listenbrainz: { ...listenbrainzSchema, nullable: true },
lang: { type: 'string', enum: [null, ...Object.keys(langmap)] as string[], nullable: true },
lang: { type: 'string', enum: [null, ...langs] as string[], nullable: true },
avatarId: { type: 'string', format: 'misskey:id', nullable: true },
avatarDecorations: { type: 'array', maxItems: 16, items: {
type: 'object',

View file

@ -20,7 +20,7 @@ import { isPureRenote } from '@/misc/is-pure-renote.js';
import { MetaService } from '@/core/MetaService.js';
import { UtilityService } from '@/core/UtilityService.js';
import { IdentifiableError } from '@/misc/identifiable-error.js';
import { langmap } from '@/misc/langmap.js';
import { langs } from '@/misc/langmap.js';
import { ApiError } from '../../error.js';
export const meta = {
@ -137,7 +137,7 @@ export const paramDef = {
visibleUserIds: { type: 'array', uniqueItems: true, items: {
type: 'string', format: 'misskey:id',
} },
lang: { type: 'string', enum: Object.keys(langmap), nullable: true, maxLength: 10 },
lang: { type: 'string', enum: langs, nullable: true, maxLength: 10 },
cw: { type: 'string', nullable: true, minLength: 1, maxLength: 500 },
localOnly: { type: 'boolean', default: false },
reactionAcceptance: { type: 'string', nullable: true, enum: [null, 'likeOnly', 'likeOnlyForRemote', 'nonSensitiveOnly', 'nonSensitiveOnlyForLocalLikeOnlyForRemote'], default: null },

View file

@ -12,7 +12,7 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { NoteEditService } from '@/core/NoteEditService.js';
import { DI } from '@/di-symbols.js';
import { IdentifiableError } from '@/misc/identifiable-error.js';
import { langmap } from '@/misc/langmap.js';
import { langs } from '@/misc/langmap.js';
import { ApiError } from '../../error.js';
export const meta = {
@ -165,7 +165,7 @@ export const paramDef = {
format: 'misskey:id',
},
},
lang: { type: 'string', enum: Object.keys(langmap), nullable: true, maxLength: 10 },
lang: { type: 'string', enum: langs, nullable: true, maxLength: 10 },
cw: { type: 'string', nullable: true, minLength: 1, maxLength: 500 },
localOnly: { type: 'boolean', default: false },
reactionAcceptance: { type: 'string', nullable: true, enum: [null, 'likeOnly', 'likeOnlyForRemote', 'nonSensitiveOnly', 'nonSensitiveOnlyForLocalLikeOnlyForRemote'], default: null },

View file

@ -134,7 +134,7 @@ import { miLocalStorage } from '@/local-storage.js';
import { claimAchievement } from '@/scripts/achievements.js';
import { emojiPicker } from '@/scripts/emoji-picker.js';
import { mfmFunctionPicker } from '@/scripts/mfm-function-picker.js';
import { langmap } from '@/scripts/langmap.js';
import { langmap, langs } from '@/scripts/langmap.js';
import { MenuItem } from '@/types/menu.js';
const $i = signinRequired();
@ -547,7 +547,6 @@ async function toggleReactionAcceptance() {
function attemptNormalizeLang(lang: string | null) {
if (lang == null) return null;
const langs = Object.keys(langmap);
if (!langs[lang]) lang = lang.split('-')[0];
return lang;
}
@ -562,8 +561,6 @@ function setLanguage(ev: MouseEvent) {
action: () => {},
});
const langs = Object.keys(langmap);
// Show recently used language first
let recentlyUsedLanguagesExist = false;
for (const lang of defaultStore.state.recentlyUsedPostLanguages) {
@ -959,11 +956,10 @@ async function post(ev?: MouseEvent) {
// update recentlyUsedLanguages
if (language.value != null) {
const languages = Object.keys(langmap);
const maxLength = 6;
defaultStore.set('recentlyUsedPostLanguages', [language.value].concat(defaultStore.state.recentlyUsedPostLanguages.filter((lang) => {
return (lang !== language.value && languages.includes(lang));
return (lang !== language.value && langs.includes(lang));
})).slice(0, maxLength));
}
}

View file

@ -45,7 +45,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkSelect v-model="profile.lang">
<template #label>{{ i18n.ts.language }}</template>
<option v-for="x in Object.keys(langmap)" :key="x" :value="x">{{ langmap[x].nativeName }}</option>
<option v-for="x in langs" :key="x" :value="x">{{ langmap[x].nativeName }}</option>
</MkSelect>
<FormSlot>
@ -128,7 +128,7 @@ import { selectFile } from '@/scripts/select-file.js';
import * as os from '@/os.js';
import { i18n } from '@/i18n.js';
import { signinRequired } from '@/account.js';
import { langmap } from '@/scripts/langmap.js';
import { langmap, langs } from '@/scripts/langmap.js';
import { definePageMetadata } from '@/scripts/page-metadata.js';
import { claimAchievement } from '@/scripts/achievements.js';
import { defaultStore } from '@/store.js';

View file

@ -385,3 +385,4 @@ export const iso639Regional = {
};
export const langmap = Object.assign({}, langmapNoRegion, iso639Regional);
export const langs = Object.keys(langmap);