mirror of
https://git.joinsharkey.org/Sharkey/Sharkey.git
synced 2024-11-22 16:13:09 +02:00
feat: Add langPref config option
This commit is contained in:
parent
4f45e72799
commit
8a416cd302
13 changed files with 78 additions and 40 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 });
|
||||
|
|
|
@ -385,3 +385,4 @@ export const iso639Regional = {
|
|||
};
|
||||
|
||||
export const langmap = Object.assign({}, langmapNoRegion, iso639Regional);
|
||||
export const langs = Object.keys(langmap);
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -385,3 +385,4 @@ export const iso639Regional = {
|
|||
};
|
||||
|
||||
export const langmap = Object.assign({}, langmapNoRegion, iso639Regional);
|
||||
export const langs = Object.keys(langmap);
|
||||
|
|
Loading…
Reference in a new issue