feat: Add language metadata to notes
This commit is contained in:
parent
2fa0e238b7
commit
a76d3cf861
20 changed files with 630 additions and 923 deletions
|
|
@ -63,6 +63,7 @@ import { trackPromise } from '@/misc/promise-tracker.js';
|
|||
import { isUserRelated } from '@/misc/is-user-related.js';
|
||||
import { isNotNull } from '@/misc/is-not-null.js';
|
||||
import { IdentifiableError } from '@/misc/identifiable-error.js';
|
||||
import { langmap } from '@/misc/langmap.js';
|
||||
|
||||
type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';
|
||||
|
||||
|
|
@ -133,6 +134,7 @@ type Option = {
|
|||
createdAt?: Date | null;
|
||||
name?: string | null;
|
||||
text?: string | null;
|
||||
lang?: string | null;
|
||||
reply?: MiNote | null;
|
||||
renote?: MiNote | null;
|
||||
files?: MiDriveFile[] | null;
|
||||
|
|
@ -337,6 +339,13 @@ export class NoteCreateService implements OnApplicationShutdown {
|
|||
data.text = null;
|
||||
}
|
||||
|
||||
if (data.lang) {
|
||||
if (!Object.keys(langmap).includes(data.lang.toLowerCase())) throw new Error('invalid param');
|
||||
data.lang = data.lang.toLowerCase();
|
||||
} else {
|
||||
data.lang = null;
|
||||
}
|
||||
|
||||
let tags = data.apHashtags;
|
||||
let emojis = data.apEmojis;
|
||||
let mentionedUsers = data.apMentions;
|
||||
|
|
@ -579,6 +588,7 @@ export class NoteCreateService implements OnApplicationShutdown {
|
|||
: null,
|
||||
name: data.name,
|
||||
text: data.text,
|
||||
lang: data.lang,
|
||||
hasPoll: data.poll != null,
|
||||
cw: data.cw ?? null,
|
||||
tags: tags.map(tag => normalizeForSearch(tag)),
|
||||
|
|
@ -1004,7 +1014,7 @@ export class NoteCreateService implements OnApplicationShutdown {
|
|||
removeOnComplete: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Pack the note
|
||||
const noteObj = await this.noteEntityService.pack(note, null, { skipHide: true, withReactionAndUserPairCache: true });
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ import { isReply } from '@/misc/is-reply.js';
|
|||
import { trackPromise } from '@/misc/promise-tracker.js';
|
||||
import { isUserRelated } from '@/misc/is-user-related.js';
|
||||
import { IdentifiableError } from '@/misc/identifiable-error.js';
|
||||
import { langmap } from '@/misc/langmap.js';
|
||||
|
||||
type NotificationType = 'reply' | 'renote' | 'quote' | 'mention' | 'edited';
|
||||
|
||||
|
|
@ -122,6 +123,7 @@ type Option = {
|
|||
createdAt?: Date | null;
|
||||
name?: string | null;
|
||||
text?: string | null;
|
||||
lang?: string | null;
|
||||
reply?: MiNote | null;
|
||||
renote?: MiNote | null;
|
||||
files?: MiDriveFile[] | null;
|
||||
|
|
@ -358,6 +360,13 @@ export class NoteEditService implements OnApplicationShutdown {
|
|||
data.text = null;
|
||||
}
|
||||
|
||||
if (data.lang) {
|
||||
if (!Object.keys(langmap).includes(data.lang.toLowerCase())) throw new Error('invalid param');
|
||||
data.lang = data.lang.toLowerCase();
|
||||
} else {
|
||||
data.lang = null;
|
||||
}
|
||||
|
||||
let tags = data.apHashtags;
|
||||
let emojis = data.apEmojis;
|
||||
let mentionedUsers = data.apMentions;
|
||||
|
|
@ -420,6 +429,9 @@ export class NoteEditService implements OnApplicationShutdown {
|
|||
if (oldnote.hasPoll !== !!data.poll) {
|
||||
update.hasPoll = !!data.poll;
|
||||
}
|
||||
if (data.lang !== oldnote.lang) {
|
||||
update.lang = data.lang;
|
||||
}
|
||||
|
||||
const poll = await this.pollsRepository.findOneBy({ noteId: oldnote.id });
|
||||
|
||||
|
|
@ -434,6 +446,7 @@ export class NoteEditService implements OnApplicationShutdown {
|
|||
oldText: oldnote.text || undefined,
|
||||
newText: update.text || undefined,
|
||||
cw: update.cw || undefined,
|
||||
lang: update.lang || undefined,
|
||||
fileIds: undefined,
|
||||
oldDate: exists ? oldnote.updatedAt as Date : this.idService.parse(oldnote.id).date,
|
||||
updatedAt: new Date(),
|
||||
|
|
@ -453,6 +466,7 @@ export class NoteEditService implements OnApplicationShutdown {
|
|||
: null,
|
||||
name: data.name,
|
||||
text: data.text,
|
||||
lang: data.lang,
|
||||
hasPoll: data.poll != null,
|
||||
cw: data.cw ?? null,
|
||||
tags: tags.map(tag => normalizeForSearch(tag)),
|
||||
|
|
|
|||
|
|
@ -285,7 +285,7 @@ export class ApRendererService {
|
|||
if (instance && instance.softwareName === 'pleroma') isMastodon = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const object: ILike = {
|
||||
type: 'Like',
|
||||
id: `${this.config.url}/likes/${noteReaction.id}`,
|
||||
|
|
@ -454,6 +454,9 @@ export class ApRendererService {
|
|||
mediaType: 'text/x.misskeymarkdown',
|
||||
},
|
||||
}),
|
||||
contentMap: note.lang ? {
|
||||
[note.lang]: content,
|
||||
} : null,
|
||||
_misskey_quote: quote,
|
||||
quoteUrl: quote,
|
||||
quoteUri: quote,
|
||||
|
|
@ -746,6 +749,9 @@ export class ApRendererService {
|
|||
mediaType: 'text/x.misskeymarkdown',
|
||||
},
|
||||
}),
|
||||
contentMap: note.lang ? {
|
||||
[note.lang]: content,
|
||||
} : null,
|
||||
_misskey_quote: quote,
|
||||
quoteUrl: quote,
|
||||
quoteUri: quote,
|
||||
|
|
|
|||
|
|
@ -25,6 +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 { getOneApId, getApId, getOneApHrefNullable, validPost, isEmoji, getApType } from '../type.js';
|
||||
import { ApLoggerService } from '../ApLoggerService.js';
|
||||
import { ApMfmService } from '../ApMfmService.js';
|
||||
|
|
@ -244,12 +245,21 @@ export class ApNoteService {
|
|||
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 (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].toLowerCase();
|
||||
lang = Object.keys(langmap).includes(key) ? key : null;
|
||||
}
|
||||
|
||||
// vote
|
||||
if (reply && reply.hasPoll) {
|
||||
const poll = await this.pollsRepository.findOneByOrFail({ noteId: reply.id });
|
||||
|
|
@ -290,6 +300,7 @@ export class ApNoteService {
|
|||
name: note.name,
|
||||
cw,
|
||||
text,
|
||||
lang,
|
||||
localOnly: false,
|
||||
visibility,
|
||||
visibleUsers,
|
||||
|
|
@ -452,12 +463,21 @@ export class ApNoteService {
|
|||
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 (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].toLowerCase();
|
||||
lang = Object.keys(langmap).includes(key) ? key : null;
|
||||
}
|
||||
|
||||
// vote
|
||||
if (reply && reply.hasPoll) {
|
||||
const poll = await this.pollsRepository.findOneByOrFail({ noteId: reply.id });
|
||||
|
|
@ -498,6 +518,7 @@ export class ApNoteService {
|
|||
name: note.name,
|
||||
cw,
|
||||
text,
|
||||
lang,
|
||||
localOnly: false,
|
||||
visibility,
|
||||
visibleUsers,
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ export interface IObject {
|
|||
inReplyTo?: any;
|
||||
replies?: ICollection;
|
||||
content?: string | null;
|
||||
contentMap?: Obj | null;
|
||||
startTime?: Date;
|
||||
endTime?: Date;
|
||||
icon?: any;
|
||||
|
|
|
|||
|
|
@ -17,12 +17,12 @@ import { bindThis } from '@/decorators.js';
|
|||
import { isNotNull } from '@/misc/is-not-null.js';
|
||||
import { DebounceLoader } from '@/misc/loader.js';
|
||||
import { IdService } from '@/core/IdService.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import type { OnModuleInit } from '@nestjs/common';
|
||||
import type { CustomEmojiService } from '../CustomEmojiService.js';
|
||||
import type { ReactionService } from '../ReactionService.js';
|
||||
import type { UserEntityService } from './UserEntityService.js';
|
||||
import type { DriveFileEntityService } from './DriveFileEntityService.js';
|
||||
import type { Config } from '@/config.js';
|
||||
|
||||
@Injectable()
|
||||
export class NoteEntityService implements OnModuleInit {
|
||||
|
|
@ -120,7 +120,7 @@ export class NoteEntityService implements OnModuleInit {
|
|||
followerId: meId,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
hide = !isFollowing;
|
||||
} else {
|
||||
// フォロワーかどうか
|
||||
|
|
@ -373,6 +373,7 @@ export class NoteEntityService implements OnModuleInit {
|
|||
uri: note.uri ?? undefined,
|
||||
url: note.url ?? undefined,
|
||||
poll: note.hasPoll ? this.populatePoll(note, meId) : undefined,
|
||||
lang: note.lang,
|
||||
...(meId && Object.keys(note.reactions).length > 0 ? {
|
||||
myReaction: this.populateMyReaction(note, meId, options?._hint_),
|
||||
} : {}),
|
||||
|
|
|
|||
|
|
@ -4,668 +4,384 @@
|
|||
*/
|
||||
|
||||
// TODO: sharedに置いてフロントエンドのと統合したい
|
||||
export const langmap = {
|
||||
'ach': {
|
||||
nativeName: 'Lwo',
|
||||
},
|
||||
'ady': {
|
||||
nativeName: 'Адыгэбзэ',
|
||||
},
|
||||
'af': {
|
||||
export const iso639Langs1 = {
|
||||
af: {
|
||||
nativeName: 'Afrikaans',
|
||||
},
|
||||
'af-NA': {
|
||||
nativeName: 'Afrikaans (Namibia)',
|
||||
},
|
||||
'af-ZA': {
|
||||
nativeName: 'Afrikaans (South Africa)',
|
||||
},
|
||||
'ak': {
|
||||
ak: {
|
||||
nativeName: 'Tɕɥi',
|
||||
},
|
||||
'ar': {
|
||||
ar: {
|
||||
nativeName: 'العربية',
|
||||
rtl: true,
|
||||
},
|
||||
'ar-AR': {
|
||||
nativeName: 'العربية',
|
||||
},
|
||||
'ar-MA': {
|
||||
nativeName: 'العربية',
|
||||
},
|
||||
'ar-SA': {
|
||||
nativeName: 'العربية (السعودية)',
|
||||
},
|
||||
'ay-BO': {
|
||||
ay: {
|
||||
nativeName: 'Aymar aru',
|
||||
},
|
||||
'az': {
|
||||
az: {
|
||||
nativeName: 'Azərbaycan dili',
|
||||
},
|
||||
'az-AZ': {
|
||||
nativeName: 'Azərbaycan dili',
|
||||
},
|
||||
'be-BY': {
|
||||
be: {
|
||||
nativeName: 'Беларуская',
|
||||
},
|
||||
'bg': {
|
||||
bg: {
|
||||
nativeName: 'Български',
|
||||
},
|
||||
'bg-BG': {
|
||||
nativeName: 'Български',
|
||||
},
|
||||
'bn': {
|
||||
bn: {
|
||||
nativeName: 'বাংলা',
|
||||
},
|
||||
'bn-IN': {
|
||||
nativeName: 'বাংলা (ভারত)',
|
||||
},
|
||||
'bn-BD': {
|
||||
nativeName: 'বাংলা(বাংলাদেশ)',
|
||||
},
|
||||
'br': {
|
||||
br: {
|
||||
nativeName: 'Brezhoneg',
|
||||
},
|
||||
'bs-BA': {
|
||||
bs: {
|
||||
nativeName: 'Bosanski',
|
||||
},
|
||||
'ca': {
|
||||
ca: {
|
||||
nativeName: 'Català',
|
||||
},
|
||||
'ca-ES': {
|
||||
nativeName: 'Català',
|
||||
},
|
||||
'cak': {
|
||||
nativeName: 'Maya Kaqchikel',
|
||||
},
|
||||
'ck-US': {
|
||||
nativeName: 'ᏣᎳᎩ (tsalagi)',
|
||||
},
|
||||
'cs': {
|
||||
cs: {
|
||||
nativeName: 'Čeština',
|
||||
},
|
||||
'cs-CZ': {
|
||||
nativeName: 'Čeština',
|
||||
},
|
||||
'cy': {
|
||||
cy: {
|
||||
nativeName: 'Cymraeg',
|
||||
},
|
||||
'cy-GB': {
|
||||
nativeName: 'Cymraeg',
|
||||
},
|
||||
'da': {
|
||||
da: {
|
||||
nativeName: 'Dansk',
|
||||
},
|
||||
'da-DK': {
|
||||
nativeName: 'Dansk',
|
||||
},
|
||||
'de': {
|
||||
de: {
|
||||
nativeName: 'Deutsch',
|
||||
},
|
||||
'de-AT': {
|
||||
nativeName: 'Deutsch (Österreich)',
|
||||
},
|
||||
'de-DE': {
|
||||
nativeName: 'Deutsch (Deutschland)',
|
||||
},
|
||||
'de-CH': {
|
||||
nativeName: 'Deutsch (Schweiz)',
|
||||
},
|
||||
'dsb': {
|
||||
nativeName: 'Dolnoserbšćina',
|
||||
},
|
||||
'el': {
|
||||
el: {
|
||||
nativeName: 'Ελληνικά',
|
||||
},
|
||||
'el-GR': {
|
||||
nativeName: 'Ελληνικά',
|
||||
},
|
||||
'en': {
|
||||
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': {
|
||||
eo: {
|
||||
nativeName: 'Esperanto',
|
||||
},
|
||||
'eo-EO': {
|
||||
nativeName: 'Esperanto',
|
||||
},
|
||||
'es': {
|
||||
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': {
|
||||
et: {
|
||||
nativeName: 'eesti keel',
|
||||
},
|
||||
'et-EE': {
|
||||
nativeName: 'Eesti (Estonia)',
|
||||
},
|
||||
'eu': {
|
||||
eu: {
|
||||
nativeName: 'Euskara',
|
||||
},
|
||||
'eu-ES': {
|
||||
nativeName: 'Euskara',
|
||||
},
|
||||
'fa': {
|
||||
fa: {
|
||||
nativeName: 'فارسی',
|
||||
rtl: true,
|
||||
},
|
||||
'fa-IR': {
|
||||
nativeName: 'فارسی',
|
||||
},
|
||||
'fb-LT': {
|
||||
nativeName: 'Leet Speak',
|
||||
},
|
||||
'ff': {
|
||||
ff: {
|
||||
nativeName: 'Fulah',
|
||||
},
|
||||
'fi': {
|
||||
fi: {
|
||||
nativeName: 'Suomi',
|
||||
},
|
||||
'fi-FI': {
|
||||
nativeName: 'Suomi',
|
||||
},
|
||||
'fo': {
|
||||
fo: {
|
||||
nativeName: 'Føroyskt',
|
||||
},
|
||||
'fo-FO': {
|
||||
nativeName: 'Føroyskt (Færeyjar)',
|
||||
},
|
||||
'fr': {
|
||||
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': {
|
||||
ga: {
|
||||
nativeName: 'Gaeilge',
|
||||
},
|
||||
'ga-IE': {
|
||||
nativeName: 'Gaeilge',
|
||||
},
|
||||
'gd': {
|
||||
gd: {
|
||||
nativeName: 'Gàidhlig',
|
||||
},
|
||||
'gl': {
|
||||
gl: {
|
||||
nativeName: 'Galego',
|
||||
},
|
||||
'gl-ES': {
|
||||
nativeName: 'Galego',
|
||||
},
|
||||
'gn-PY': {
|
||||
gn: {
|
||||
nativeName: 'Avañe\'ẽ',
|
||||
},
|
||||
'gu-IN': {
|
||||
gu: {
|
||||
nativeName: 'ગુજરાતી',
|
||||
},
|
||||
'gv': {
|
||||
gv: {
|
||||
nativeName: 'Gaelg',
|
||||
},
|
||||
'gx-GR': {
|
||||
nativeName: 'Ἑλληνική ἀρχαία',
|
||||
},
|
||||
'he': {
|
||||
he: {
|
||||
nativeName: 'עברית',
|
||||
rtl: true,
|
||||
},
|
||||
'he-IL': {
|
||||
nativeName: 'עברית',
|
||||
},
|
||||
'hi': {
|
||||
hi: {
|
||||
nativeName: 'हिन्दी',
|
||||
},
|
||||
'hi-IN': {
|
||||
nativeName: 'हिन्दी',
|
||||
},
|
||||
'hr': {
|
||||
hr: {
|
||||
nativeName: 'Hrvatski',
|
||||
},
|
||||
'hr-HR': {
|
||||
nativeName: 'Hrvatski',
|
||||
},
|
||||
'hsb': {
|
||||
nativeName: 'Hornjoserbšćina',
|
||||
},
|
||||
'ht': {
|
||||
ht: {
|
||||
nativeName: 'Kreyòl',
|
||||
},
|
||||
'hu': {
|
||||
hu: {
|
||||
nativeName: 'Magyar',
|
||||
},
|
||||
'hu-HU': {
|
||||
nativeName: 'Magyar',
|
||||
},
|
||||
'hy': {
|
||||
hy: {
|
||||
nativeName: 'Հայերեն',
|
||||
},
|
||||
'hy-AM': {
|
||||
nativeName: 'Հայերեն (Հայաստան)',
|
||||
},
|
||||
'id': {
|
||||
id: {
|
||||
nativeName: 'Bahasa Indonesia',
|
||||
},
|
||||
'id-ID': {
|
||||
nativeName: 'Bahasa Indonesia',
|
||||
},
|
||||
'is': {
|
||||
is: {
|
||||
nativeName: 'Íslenska',
|
||||
},
|
||||
'is-IS': {
|
||||
nativeName: 'Íslenska (Iceland)',
|
||||
},
|
||||
'it': {
|
||||
it: {
|
||||
nativeName: 'Italiano',
|
||||
},
|
||||
'it-IT': {
|
||||
nativeName: 'Italiano',
|
||||
},
|
||||
'ja': {
|
||||
ja: {
|
||||
nativeName: '日本語',
|
||||
},
|
||||
'ja-JP': {
|
||||
nativeName: '日本語 (日本)',
|
||||
},
|
||||
'jv-ID': {
|
||||
jv: {
|
||||
nativeName: 'Basa Jawa',
|
||||
},
|
||||
'ka-GE': {
|
||||
ka: {
|
||||
nativeName: 'ქართული',
|
||||
},
|
||||
'kk-KZ': {
|
||||
kk: {
|
||||
nativeName: 'Қазақша',
|
||||
},
|
||||
'km': {
|
||||
nativeName: 'ភាសាខ្មែរ',
|
||||
},
|
||||
'kl': {
|
||||
kl: {
|
||||
nativeName: 'kalaallisut',
|
||||
},
|
||||
'km-KH': {
|
||||
km: {
|
||||
nativeName: 'ភាសាខ្មែរ',
|
||||
},
|
||||
'kab': {
|
||||
nativeName: 'Taqbaylit',
|
||||
},
|
||||
'kn': {
|
||||
kn: {
|
||||
nativeName: 'ಕನ್ನಡ',
|
||||
},
|
||||
'kn-IN': {
|
||||
nativeName: 'ಕನ್ನಡ (India)',
|
||||
},
|
||||
'ko': {
|
||||
ko: {
|
||||
nativeName: '한국어',
|
||||
},
|
||||
'ko-KR': {
|
||||
nativeName: '한국어 (한국)',
|
||||
},
|
||||
'ku-TR': {
|
||||
ku: {
|
||||
nativeName: 'Kurdî',
|
||||
},
|
||||
'kw': {
|
||||
kw: {
|
||||
nativeName: 'Kernewek',
|
||||
},
|
||||
'la': {
|
||||
la: {
|
||||
nativeName: 'Latin',
|
||||
},
|
||||
'la-VA': {
|
||||
nativeName: 'Latin',
|
||||
},
|
||||
'lb': {
|
||||
lb: {
|
||||
nativeName: 'Lëtzebuergesch',
|
||||
},
|
||||
'li-NL': {
|
||||
li: {
|
||||
nativeName: 'Lèmbörgs',
|
||||
},
|
||||
'lt': {
|
||||
lt: {
|
||||
nativeName: 'Lietuvių',
|
||||
},
|
||||
'lt-LT': {
|
||||
nativeName: 'Lietuvių',
|
||||
},
|
||||
'lv': {
|
||||
lv: {
|
||||
nativeName: 'Latviešu',
|
||||
},
|
||||
'lv-LV': {
|
||||
nativeName: 'Latviešu',
|
||||
},
|
||||
'mai': {
|
||||
nativeName: 'मैथिली, মৈথিলী',
|
||||
},
|
||||
'mg-MG': {
|
||||
mg: {
|
||||
nativeName: 'Malagasy',
|
||||
},
|
||||
'mk': {
|
||||
mk: {
|
||||
nativeName: 'Македонски',
|
||||
},
|
||||
'mk-MK': {
|
||||
nativeName: 'Македонски (Македонски)',
|
||||
},
|
||||
'ml': {
|
||||
ml: {
|
||||
nativeName: 'മലയാളം',
|
||||
},
|
||||
'ml-IN': {
|
||||
nativeName: 'മലയാളം',
|
||||
},
|
||||
'mn-MN': {
|
||||
mn: {
|
||||
nativeName: 'Монгол',
|
||||
},
|
||||
'mr': {
|
||||
mr: {
|
||||
nativeName: 'मराठी',
|
||||
},
|
||||
'mr-IN': {
|
||||
nativeName: 'मराठी',
|
||||
},
|
||||
'ms': {
|
||||
ms: {
|
||||
nativeName: 'Bahasa Melayu',
|
||||
},
|
||||
'ms-MY': {
|
||||
nativeName: 'Bahasa Melayu',
|
||||
},
|
||||
'mt': {
|
||||
mt: {
|
||||
nativeName: 'Malti',
|
||||
},
|
||||
'mt-MT': {
|
||||
nativeName: 'Malti',
|
||||
},
|
||||
'my': {
|
||||
my: {
|
||||
nativeName: 'ဗမာစကာ',
|
||||
},
|
||||
'no': {
|
||||
no: {
|
||||
nativeName: 'Norsk',
|
||||
},
|
||||
'nb': {
|
||||
nb: {
|
||||
nativeName: 'Norsk (bokmål)',
|
||||
},
|
||||
'nb-NO': {
|
||||
nativeName: 'Norsk (bokmål)',
|
||||
},
|
||||
'ne': {
|
||||
ne: {
|
||||
nativeName: 'नेपाली',
|
||||
},
|
||||
'ne-NP': {
|
||||
nativeName: 'नेपाली',
|
||||
},
|
||||
'nl': {
|
||||
nl: {
|
||||
nativeName: 'Nederlands',
|
||||
},
|
||||
'nl-BE': {
|
||||
nativeName: 'Nederlands (België)',
|
||||
},
|
||||
'nl-NL': {
|
||||
nativeName: 'Nederlands (Nederland)',
|
||||
},
|
||||
'nn-NO': {
|
||||
nn: {
|
||||
nativeName: 'Norsk (nynorsk)',
|
||||
},
|
||||
'oc': {
|
||||
oc: {
|
||||
nativeName: 'Occitan',
|
||||
},
|
||||
'or-IN': {
|
||||
or: {
|
||||
nativeName: 'ଓଡ଼ିଆ',
|
||||
},
|
||||
'pa': {
|
||||
pa: {
|
||||
nativeName: 'ਪੰਜਾਬੀ',
|
||||
},
|
||||
'pa-IN': {
|
||||
nativeName: 'ਪੰਜਾਬੀ (ਭਾਰਤ ਨੂੰ)',
|
||||
},
|
||||
'pl': {
|
||||
pl: {
|
||||
nativeName: 'Polski',
|
||||
},
|
||||
'pl-PL': {
|
||||
nativeName: 'Polski',
|
||||
},
|
||||
'ps-AF': {
|
||||
ps: {
|
||||
nativeName: 'پښتو',
|
||||
rtl: true,
|
||||
},
|
||||
'pt': {
|
||||
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': {
|
||||
ro: {
|
||||
nativeName: 'Română',
|
||||
},
|
||||
'ro-RO': {
|
||||
nativeName: 'Română',
|
||||
},
|
||||
'ru': {
|
||||
ru: {
|
||||
nativeName: 'Русский',
|
||||
},
|
||||
'ru-RU': {
|
||||
nativeName: 'Русский',
|
||||
},
|
||||
'sa-IN': {
|
||||
sa: {
|
||||
nativeName: 'संस्कृतम्',
|
||||
},
|
||||
'se-NO': {
|
||||
se: {
|
||||
nativeName: 'Davvisámegiella',
|
||||
},
|
||||
'sh': {
|
||||
sh: {
|
||||
nativeName: 'српскохрватски',
|
||||
},
|
||||
'si-LK': {
|
||||
si: {
|
||||
nativeName: 'සිංහල',
|
||||
},
|
||||
'sk': {
|
||||
sk: {
|
||||
nativeName: 'Slovenčina',
|
||||
},
|
||||
'sk-SK': {
|
||||
nativeName: 'Slovenčina (Slovakia)',
|
||||
},
|
||||
'sl': {
|
||||
sl: {
|
||||
nativeName: 'Slovenščina',
|
||||
},
|
||||
'sl-SI': {
|
||||
nativeName: 'Slovenščina',
|
||||
},
|
||||
'so-SO': {
|
||||
so: {
|
||||
nativeName: 'Soomaaliga',
|
||||
},
|
||||
'sq': {
|
||||
sq: {
|
||||
nativeName: 'Shqip',
|
||||
},
|
||||
'sq-AL': {
|
||||
nativeName: 'Shqip',
|
||||
},
|
||||
'sr': {
|
||||
sr: {
|
||||
nativeName: 'Српски',
|
||||
},
|
||||
'sr-RS': {
|
||||
nativeName: 'Српски (Serbia)',
|
||||
},
|
||||
'su': {
|
||||
su: {
|
||||
nativeName: 'Basa Sunda',
|
||||
},
|
||||
'sv': {
|
||||
sv: {
|
||||
nativeName: 'Svenska',
|
||||
},
|
||||
'sv-SE': {
|
||||
nativeName: 'Svenska',
|
||||
},
|
||||
'sw': {
|
||||
sw: {
|
||||
nativeName: 'Kiswahili',
|
||||
},
|
||||
'sw-KE': {
|
||||
nativeName: 'Kiswahili',
|
||||
},
|
||||
'ta': {
|
||||
ta: {
|
||||
nativeName: 'தமிழ்',
|
||||
},
|
||||
'ta-IN': {
|
||||
nativeName: 'தமிழ்',
|
||||
},
|
||||
'te': {
|
||||
te: {
|
||||
nativeName: 'తెలుగు',
|
||||
},
|
||||
'te-IN': {
|
||||
nativeName: 'తెలుగు',
|
||||
},
|
||||
'tg': {
|
||||
tg: {
|
||||
nativeName: 'забо́ни тоҷикӣ́',
|
||||
},
|
||||
'tg-TJ': {
|
||||
nativeName: 'тоҷикӣ',
|
||||
},
|
||||
'th': {
|
||||
th: {
|
||||
nativeName: 'ภาษาไทย',
|
||||
},
|
||||
'th-TH': {
|
||||
nativeName: 'ภาษาไทย (ประเทศไทย)',
|
||||
},
|
||||
'fil': {
|
||||
nativeName: 'Filipino',
|
||||
},
|
||||
'tlh': {
|
||||
nativeName: 'tlhIngan-Hol',
|
||||
},
|
||||
'tr': {
|
||||
tr: {
|
||||
nativeName: 'Türkçe',
|
||||
},
|
||||
'tr-TR': {
|
||||
nativeName: 'Türkçe',
|
||||
},
|
||||
'tt-RU': {
|
||||
tt: {
|
||||
nativeName: 'татарча',
|
||||
},
|
||||
'uk': {
|
||||
uk: {
|
||||
nativeName: 'Українська',
|
||||
},
|
||||
'uk-UA': {
|
||||
nativeName: 'Українська',
|
||||
},
|
||||
'ur': {
|
||||
ur: {
|
||||
nativeName: 'اردو',
|
||||
rtl: true,
|
||||
},
|
||||
'ur-PK': {
|
||||
nativeName: 'اردو',
|
||||
},
|
||||
'uz': {
|
||||
uz: {
|
||||
nativeName: 'O\'zbek',
|
||||
},
|
||||
'uz-UZ': {
|
||||
nativeName: 'O\'zbek',
|
||||
},
|
||||
'vi': {
|
||||
vi: {
|
||||
nativeName: 'Tiếng Việt',
|
||||
},
|
||||
'vi-VN': {
|
||||
nativeName: 'Tiếng Việt',
|
||||
},
|
||||
'xh-ZA': {
|
||||
xh: {
|
||||
nativeName: 'isiXhosa',
|
||||
},
|
||||
'yi': {
|
||||
yi: {
|
||||
nativeName: 'ייִדיש',
|
||||
rtl: true,
|
||||
},
|
||||
'yi-DE': {
|
||||
nativeName: 'ייִדיש (German)',
|
||||
},
|
||||
'zh': {
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -61,6 +61,12 @@ export class MiNote {
|
|||
})
|
||||
public text: string | null;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 10,
|
||||
nullable: true,
|
||||
})
|
||||
public lang: string | null;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 256, nullable: true,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Entity, JoinColumn, Column, ManyToOne, PrimaryColumn, Index } from "typeorm";
|
||||
import { Entity, JoinColumn, Column, ManyToOne, PrimaryColumn, Index } from 'typeorm';
|
||||
import { id } from './util/id.js';
|
||||
import { MiNote } from './Note.js';
|
||||
import type { MiDriveFile } from './DriveFile.js';
|
||||
|
|
@ -11,46 +11,52 @@ export class NoteEdit {
|
|||
@Index()
|
||||
@Column({
|
||||
...id(),
|
||||
comment: "The ID of note.",
|
||||
comment: 'The ID of note.',
|
||||
})
|
||||
public noteId: MiNote["id"];
|
||||
public noteId: MiNote['id'];
|
||||
|
||||
@ManyToOne((type) => MiNote, {
|
||||
onDelete: "CASCADE",
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
public note: MiNote | null;
|
||||
|
||||
@Column("text", {
|
||||
@Column('text', {
|
||||
nullable: true,
|
||||
})
|
||||
public oldText: string | null;
|
||||
|
||||
@Column("text", {
|
||||
@Column('text', {
|
||||
nullable: true,
|
||||
})
|
||||
public newText: string | null;
|
||||
|
||||
@Column("varchar", {
|
||||
@Column('varchar', {
|
||||
length: 512,
|
||||
nullable: true,
|
||||
})
|
||||
public cw: string | null;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 10,
|
||||
nullable: true,
|
||||
})
|
||||
public lang: string | null;
|
||||
|
||||
@Column({
|
||||
...id(),
|
||||
array: true,
|
||||
default: "{}",
|
||||
default: '{}',
|
||||
})
|
||||
public fileIds: MiDriveFile["id"][];
|
||||
public fileIds: MiDriveFile['id'][];
|
||||
|
||||
@Column("timestamp with time zone", {
|
||||
comment: "The updated date of the Note.",
|
||||
@Column('timestamp with time zone', {
|
||||
comment: 'The updated date of the Note.',
|
||||
})
|
||||
public updatedAt: Date;
|
||||
|
||||
@Column("timestamp with time zone", {
|
||||
comment: "The old date from before the edit",
|
||||
@Column('timestamp with time zone', {
|
||||
comment: 'The old date from before the edit',
|
||||
})
|
||||
public oldDate: Date;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { langmap } from '@/misc/langmap.js';
|
||||
|
||||
export const packedNoteSchema = {
|
||||
type: 'object',
|
||||
|
|
@ -26,6 +27,11 @@ export const packedNoteSchema = {
|
|||
type: 'string',
|
||||
optional: false, nullable: true,
|
||||
},
|
||||
lang: {
|
||||
type: 'string',
|
||||
enum: [...Object.keys(langmap)],
|
||||
nullable: true,
|
||||
},
|
||||
cw: {
|
||||
type: 'string',
|
||||
optional: true, nullable: true,
|
||||
|
|
|
|||
|
|
@ -20,6 +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 { ApiError } from '../../error.js';
|
||||
|
||||
export const meta = {
|
||||
|
|
@ -136,6 +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 },
|
||||
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 },
|
||||
|
|
@ -370,6 +372,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
expiresAt: ps.poll.expiresAt ? new Date(ps.poll.expiresAt) : null,
|
||||
} : undefined,
|
||||
text: ps.text ?? undefined,
|
||||
lang: ps.lang,
|
||||
reply,
|
||||
renote,
|
||||
cw: ps.cw,
|
||||
|
|
|
|||
|
|
@ -12,6 +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 { ApiError } from '../../error.js';
|
||||
|
||||
export const meta = {
|
||||
|
|
@ -164,6 +165,7 @@ export const paramDef = {
|
|||
format: 'misskey:id',
|
||||
},
|
||||
},
|
||||
lang: { type: 'string', enum: Object.keys(langmap), 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 },
|
||||
|
|
@ -301,7 +303,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
if (ps.renoteId === ps.editId) {
|
||||
throw new ApiError(meta.errors.cannotQuoteCurrentPost);
|
||||
}
|
||||
|
||||
|
||||
if (ps.renoteId != null) {
|
||||
// Fetch renote to note
|
||||
renote = await this.notesRepository.findOneBy({ id: ps.renoteId });
|
||||
|
|
@ -378,6 +380,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
}
|
||||
}
|
||||
|
||||
if (ps.lang) {
|
||||
if (!Object.keys(langmap).includes(ps.lang.toLowerCase())) throw new Error('invalid param');
|
||||
ps.lang = ps.lang.toLowerCase();
|
||||
} else {
|
||||
ps.lang = null;
|
||||
}
|
||||
|
||||
let channel: MiChannel | null = null;
|
||||
if (ps.channelId != null) {
|
||||
channel = await this.channelsRepository.findOneBy({ id: ps.channelId, isArchived: false });
|
||||
|
|
@ -396,6 +405,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
expiresAt: ps.poll.expiresAt ? new Date(ps.poll.expiresAt) : null,
|
||||
} : undefined,
|
||||
text: ps.text ?? undefined,
|
||||
lang: ps.lang,
|
||||
reply,
|
||||
renote,
|
||||
cw: ps.cw,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue