diff --git a/CHANGELOG.md b/CHANGELOG.md index 970a862cb..c1ff53fd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,14 @@ You should also include the user name that made the change. --> +## 13.1.4 (2023/01/22) + +### Improvements +- 新たな実績を追加 + +### Bugfixes +- Client: ローカリゼーション更新時にリロードが繰り返されることがあるのを修正 + ## 13.1.3 (2023/01/22) ### Bugfixes @@ -65,6 +73,7 @@ You should also include the user name that made the change. - Node.js 18.x or later is required - PostgreSQL 15.x is required - Misskey not using 15 specific features at 13.0.0, but may do so in the future. + - Docker環境でPostgreSQLのアップデートを行う際のガイドはこちら: https://github.com/misskey-dev/misskey/pull/9641#issue-1536336620 - Elasticsearchのサポートが削除されました - 代わりに今後任意の検索プロバイダを設定できる仕組みを構想しています。その仕組みを使えば今まで通りElasticsearchも利用できます - Yarnからpnpmに移行されました diff --git a/locales/de-DE.yml b/locales/de-DE.yml index ecead98c3..e81f7579c 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -1048,6 +1048,9 @@ _achievements: _noteFavorited1: title: "Sternengucker" description: "Eine Notiz als Favorit markiert" + _myNoteFavorited1: + title: "Sternensucher" + description: "Ein anderer Benutzer hat eine deiner Notizen als Favoriten markiert" _profileFilled: title: "Perfekte Vorbereitung" description: "Fülle dein Profil aus" diff --git a/locales/en-US.yml b/locales/en-US.yml index e398f1fd5..6a43d4569 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1048,6 +1048,9 @@ _achievements: _noteFavorited1: title: "Stargazer" description: "Favorite your first note" + _myNoteFavorited1: + title: "Seeking Stars" + description: "Have somebody else favorite one of your notes" _profileFilled: title: "Well-prepared" description: "Set up your profile" diff --git a/locales/it-IT.yml b/locales/it-IT.yml index cc93891bc..c5d89a0f5 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -1,7 +1,7 @@ --- _lang_: "Italiano" headlineMisskey: "Rete collegata tramite note" -introMisskey: "Eccoci! Misskey è un servizio di microblogging decentralizzato, libero e aperto. \n📡 Puoi pubblicare «Note» per condividere ciò che sta succedendo o per dire a tutti qualcosa su di te. \n👍 Puoi reagire inviando emoji rapidi alle «Note» provenienti da altri profili nel Fediverso.\n🚀 Esplora un nuovo mondo insieme a noi!" +introMisskey: "Eccoci! Misskey è un servizio di microblogging decentralizzato, libero e aperto. \n\n📡 Puoi pubblicare «Note» per condividere ciò che sta succedendo o per dire a tutti qualcosa su di te. \n\n👍 Puoi reagire inviando emoji rapidi alle «Note» provenienti da altri profili nel Fediverso.\n\n🚀 Esplora un nuovo mondo insieme a noi!" poweredByMisskeyDescription: "{name} è uno dei servizi (chiamati istanze) che utilizzano la piattaforma open source Misskey." monthAndDay: "{day}/{month}" search: "Cerca" @@ -943,79 +943,79 @@ _achievements: earnedAt: "Data di conseguimento" _types: _notes1: - title: "Ho iniziato a usare Misskey" - description: "Ho pubblicato la mia prima Nota" + title: "Hai iniziato a usare Misskey" + description: "Hai pubblicato la prima Nota" flavor: "Goditi la vita su Misskey!" _notes10: title: "Alcune Note" - description: "Ho inserito 10 Note" + description: "Hai inserito 10 Note" _notes100: title: "Un po' di Note" - description: "Ho inserito 100 Note" + description: "Hai inserito 100 Note" _notes500: title: "Un bel po' di Note" - description: "Ho inserito 500 Note" + description: "Hai inserito 500 Note" _notes1000: title: "Una montagna di Note" - description: "Ho inserito 1.000 Note" + description: "Hai inserito 1.000 Note" _notes5000: title: "Un sovraccarico di Note!" - description: "Ho inserito 5.000 Note" + description: "Hai inserito 5.000 Note" _notes10000: title: "SuperNote!" - description: "Ho inserito 10.000 Note" + description: "Hai inserito 10.000 Note" _notes20000: title: "Voglio più... Note!" - description: "Ho inserito 20.000 Note" + description: "Hai inserito 20.000 Note" _notes30000: title: "Note, Note, Note!" - description: "Ho inserito 30.000 Note" + description: "Hai inserito 30.000 Note" _notes40000: title: "Una fabbrica di Note" - description: "Ho inserito 40.000 Note" + description: "Hai inserito 40.000 Note" _notes50000: title: "Un pianeta di Note" - description: "Ho inserito 50.000 Note" + description: "Hai inserito 50.000 Note" _notes60000: title: "Un quasar di Note" - description: "Ho inserito 60.000 Note" + description: "Hai inserito 60.000 Note" _notes70000: title: "Un buco nero supermassiccio di Note" - description: "Ho inserito 70.000 Note" + description: "Hai inserito 70.000 Note" _notes80000: title: "Una galassia di Note" - description: "Ho inserito 80.000 Note" + description: "Hai inserito 80.000 Note" _notes90000: title: "Un universo di Note!" - description: "Ho inserito 90.000 Note" + description: "Hai inserito 90.000 Note" _notes100000: title: "ALL YOUR NOTE ARE BELONG TO US" - description: "Ho inserito 100.000 Note" + description: "Hai inserito 100.000 Note" flavor: "Hai molto da scrivere?" _login3: title: "Principiante I" - description: "Accedi per 3 giorni di fila" + description: "Accedi per un totale di 3 giorni" flavor: "Da oggi, chiamatemi Misskist" _login7: title: "Principiante II" - description: "Accedi per 7 giorni di fila" + description: "Accedi per un totale di 7 giorni" flavor: "Ti sembra di avere la situazione sotto controllo?" _login15: title: "Principiante III" - description: "Accedi per 15 giorni di fila" + description: "Accedi per un totale di 15 giorni" _login30: title: "Misskist I" - description: "Accedi per 30 giorni di fila" + description: "Accedi per un totale di 30 giorni" _login60: title: "Misskeist II" - description: "Accedi per 60 giorni di fila" + description: "Accedi per un totale di 60 giorni" _login100: title: "Misskeist III" - description: "Accedi per 100 giorni di fila" + description: "Accedi per un totale di 100 giorni" flavor: "Violent Misskeist" _login200: title: "Regolare I" - description: "Accedi per 200 giorni totali" + description: "Accedi per un totale di 200 giorni" _login300: title: "Regolare II" description: "Accedi per un totale di 300 giorni" @@ -1090,9 +1090,82 @@ _achievements: description: "Hai ottenuto 500 Follower" _followers1000: title: "Influenzer" + description: "Hai superato i 1.000 Follower" + _collectAchievements30: + title: "Collezionista di successi" + description: "Hai raggiunto 30 obiettivi" + _viewAchievements3min: + title: "Mi piacciono i risultati" + description: "Guarda la tua collezione di obiettivi per almeno 3 minuti" + _iLoveMisskey: + title: "I LOVE Misskey" + description: "Pubblica «I ♥ #Misskey»" + flavor: "Grazie per aver utilizzato Misskey! Dal team di sviluppo" + _client30min: + title: "Piccola pausa" + description: "Hai passato più di 30 minuti di fila su Misskey" + _noteDeletedWithin1min: + title: "Ooops!" + description: "Hai eliminato una nota entro un minuto dalla sua pubblicazione" + _postedAtLateNight: + title: "Biassanot!" + description: "Hai pubblicato una nota in tarda notte" + flavor: "Andiamo a dormire presto" + _postedAt0min0sec: + title: "Mezzanotte" + description: "Hai pubblicato una Nota a mezzanotte in punto" + flavor: "tic, tac, tic, tac! Gong!" + _selfQuote: + title: "Autoreferenziale" + description: "Hai citato una delle tue Note" + _htl20npm: + title: "Timeline scorrevole" + description: "La tua Timeline personale ha superato la velocità di 20 Note orarie (Note al minuto)" + _outputHelloWorldOnScratchpad: + title: "Hello, world!" + description: "Hai scritto «Hello world» nel blocco appunti" + _open3windows: + title: "Finestrato" + description: "Hai aperto almeno 3 finestre contemporaneamente" + _driveFolderCircularReference: + title: "Riferimento circolare" + description: "Hai provato a nidificare in modo ricorsivo le cartelle del Drive" + _reactWithoutRead: + title: "Hai letto bene?" + description: "Hai reagito ad una Nota più lunga di 100 caratteri entro 3 secondi dalla sua pubblicazione" + _clickedClickHere: + title: "Clicca qui" + description: "Hai cliccato qui" + _justPlainLucky: + title: "Proprio fortunato" + description: "Ottenuto con una probabilità dello 0,01% ogni 10 secondi" + _setNameToSyuilo: + title: "Complesso divino" + description: "Hai impostati il tuo nome in «syuilo»" + _passedSinceAccountCreated1: + title: "Primo Anniversario" + description: "È passato un anno da quando hai creato il profilo" + _passedSinceAccountCreated2: + title: "Secondo Anniversario" + description: "Sono passati due anni da quando hai creato il profilo" + _passedSinceAccountCreated3: + title: "Terzo Anniversario" + description: "Sono passati tre anni da quando hai creato il profilo" + _loggedInOnBirthday: + title: "Buon compleanno!" + description: "Hai effettuato l'accesso il giorno del tuo compleanno" + _loggedInOnNewYearsDay: + title: "Buon anno nuovo!" + description: "Hai usato effettuato l'accesso il giorno di capodanno" + flavor: "Anche quest'anno, grazie per il tuo continuo supporto a questa istanza" + _cookieClicked: + title: "Clicca il biscotto" + description: "Hai giocato a cliccare il cookie" + flavor: "Hai autorizzato i cookie?" _brainDiver: title: "Brain Diver" description: "Pubblica un link a Brain Diver" + flavor: "Sulle note di Brain Diver" _role: new: "Nuovo ruolo" edit: "Modifica ruolo" diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 898ae01e7..57296b985 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1049,6 +1049,9 @@ _achievements: _noteFavorited1: title: "星をみるひと" description: "初めてノートをお気に入りに登録した" + _myNoteFavorited1: + title: "星が欲しい" + description: "自分のノートが他の人からお気に入りに登録された" _profileFilled: title: "準備万端" description: "プロフィール設定を行った" diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml index f22a093ca..541941398 100644 --- a/locales/ru-RU.yml +++ b/locales/ru-RU.yml @@ -891,19 +891,48 @@ cannotUploadBecauseNoFreeSpace: "Файл не может быть загруж beta: "Бета" enableAutoSensitive: "Автоматическое определение NSFW" enableAutoSensitiveDescription: "Если доступно, используйте машинное обучение для автоматической установки флага NSFW на носителе. Даже если эта функция отключена, она может быть установлена ​​автоматически в зависимости от инстанта." +navbar: "Панель навигации" +shuffle: "Перемешать" account: "Учётные записи" +move: "Переместить" +pushNotification: "Push-уведомления" +subscribePushNotification: "Включить push-уведомления" +unsubscribePushNotification: "Выключить push-уведомления" +pushNotificationAlreadySubscribed: "Push-уведомления уже включены" +pushNotificationNotSupported: "Push-уведмления не поддерживаются инстансом или браузером" +sendPushNotificationReadMessage: "Удалять push-уведомления когда сообщение или прочитано" +sendPushNotificationReadMessageCaption: "На мгновение появится уведомление \"{emptyPushNotificationMessage}\". Расход заряда батареи может увеличиться " windowMaximize: "Развернуть" windowRestore: "Восстановить" +caption: "Подпись (Automatic Translation)" loggedInAsBot: "Вы под аккаунтом бота!" +tools: "Инструменты" +cannotLoad: "Не удалось загрузить" +numberOfProfileView: "Количество профилей для просмотра" like: "Нравится!" unlike: "Отменить «нравится»" +numberOfLikes: "Количество лайков" show: "Отображение" +neverShow: "Больше не показывать" +remindMeLater: "Напомнить позже" +didYouLikeMisskey: "Вам нравится Misskey?" pleaseDonate: "Сайт {host} работает на Misskey. Это бесплатное программное обеспечение, и ваши пожертвования очень бы помогли продолжать его разработку!" roles: "Роли" role: "Роль" +normalUser: "Обычный пользователь" +undefined: "неопределён" +assign: "Назначить" +unassign: "Отменить назначение" color: "Цвет" +manageCustomEmojis: "Управлять пользовательскими эмодзи" +youCannotCreateAnymore: "Вы достигли лимита создания." +cannotPerformTemporary: "Временно недоступен" +cannotPerformTemporaryDescription: "Это действие временно невозможно выполнить из-за превышения лимита выполнения." +preset: "Шаблоны" +selectFromPresets: "Выбрать из шаблонов" achievements: "Достижения" _achievements: + earnedAt: "Разблокировано в" _types: _notes1: title: "Первые шаги в Misskey" @@ -975,6 +1004,7 @@ _achievements: _login100: title: "Мискиец Ⅲ" description: "100 дней на сайте" + flavor: "Жестокий Misskist " _login200: title: "Завсегдатай Ⅰ" description: "200 дней на сайте" @@ -1010,6 +1040,9 @@ _achievements: _noteFavorited1: title: "Смотрящий на звёзды" description: "Первое добавление в избранное" + _myNoteFavorited1: + title: "В поиске звёзд" + description: "Кому-то понравилась ваша заметка" _profileFilled: title: "Приготовления закончены" description: "Заполнен профиль" @@ -1130,14 +1163,24 @@ _achievements: flavor: "Мисски-Мисски Ла-Ту-Ма" _role: new: "Новая роль" + edit: "Изменить роль" name: "Название роли" description: "Описание роли" permission: "Ролевые полномочия" + descriptionOfPermission: "Модераторы могут изменять базовые операции для модераторов.\nАдминистраторы могут изменять полностью настройки инстанса." assignTarget: "Метод присвоения" + descriptionOfAssignTarget: "Вручную чтобы указать кому выдавать роль, а кому нет.\nПо условию чтобы автоматически выдавать и удалять роль при условиях." manual: "Вручную" conditional: "По условию" + condition: "Условия" + isConditionalRole: "Эта роль выдаётся по условию." isPublic: "Общедоступная роль" descriptionOfIsPublic: "Список тех, кому назначена эта роль будет доступен всем. Кроме того эта роль будет отмечена у каждого в профиле." + options: "Настройки ролей" + policies: "Политики" + baseRole: "Шаблон роли" + useBaseValue: "Использовать значение из шаблона" + chooseRoleToAssign: "Выберите роль, которую хотите выдать" canEditMembersByModerator: "Могут назначать модераторы" descriptionOfCanEditMembersByModerator: "Если включено, на эту роль могут назначать пользователей как администраторы, так и модераторы. Если выключено, назначать могут только администраторы." priority: "Приоритет" @@ -1145,6 +1188,8 @@ _role: low: "Низкий" middle: "Средне" high: "Высокий" + _options: + canManageCustomEmojis: "Управлять пользовательскими эмодзи" _sensitiveMediaDetection: description: "Машинное обучение может быть использовано для автоматического обнаружения чувствительных медиа для модерации. Нагрузка на сервер увеличивается незначительно." setSensitiveFlagAutomatically: "Установить флаг NSFW" @@ -1191,6 +1236,11 @@ _plugin: install: "Установка расширений" installWarn: "Пожалуйста, не устанавливайте расширения, которым не доверяете." manage: "Управление расширениями" +_preferencesBackups: + saveConfirm: "Сохранить бэкап как {name}?" + deleteConfirm: "Удалить резервную копию {name}?" + renameConfirm: "Переименовать резервную копию с \"{old}\" на \"{new}\"?" + noBackups: "Резервной копии не существует. Вы можете создать резервную копию в настройках на этом инстансе с помощью \"Создать новую резервную копию\"." _registry: scope: "Область" key: "Ключ" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index 33127264b..22c45f516 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -992,22 +992,53 @@ _achievements: title: "ALL YOUR NOTE ARE BELONG TO US" description: "发布了100,000篇帖子" flavor: "真的有那么多可以写的东西吗?" + _login3: + title: "初学者 I" + description: "连续登录3天" + _login7: + description: "连续登录7天" + _login15: + description: "连续登录15天" + _login30: + description: "连续登录30天" + _login60: + description: "连续登录60天" _login1000: flavor: "感谢您使用Misskey!" _noteFavorited1: title: "观星者" _markedAsCat: title: "我是猫" + description: "将账户设定为一只猫" + _following10: + title: "关注,跟随" _following50: title: "我的朋友很多" + _following300: + description: "关注数超过300" + _followers100: + title: "胜友如云" + _collectAchievements30: + description: "获得超过30个成就" _viewAchievements3min: description: "盯着成就看三分钟" _iLoveMisskey: title: "I Love Misskey" description: "发布\"I ❤ #Misskey\"帖子" flavor: "感谢您使用 Misskey ! by 开发团队" + _noteDeletedWithin1min: + description: "发帖后一分钟内就将其删除" + _postedAtLateNight: + title: "夜行者" + description: "深夜发布帖子" _outputHelloWorldOnScratchpad: title: "Hello, world!" + _passedSinceAccountCreated1: + description: "账户创建时间超过1年" + _passedSinceAccountCreated2: + description: "账户创建时间超过2年" + _passedSinceAccountCreated3: + description: "账户创建时间超过3年" _loggedInOnBirthday: title: "生日快乐" description: "在生日当天登录" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index b88cfd91a..4c7e5fb19 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -1042,6 +1042,18 @@ _achievements: title: "貼文大師ⅠⅠⅠ" description: "總登入天數為1,000天" flavor: "感謝您使用Misskey!" + _noteClipped1: + title: "忍不住要收進摘錄裡" + description: "第一次將貼文收進摘錄" + _noteFavorited1: + title: "觀星者" + description: "第一次將貼文收進我的最愛" + _profileFilled: + title: "有備而來" + description: "設定了個人檔案" + _markedAsCat: + title: "我是貓" + description: "已將帳戶設定為貓" _followers500: title: "基站" description: "超過500名追隨者" diff --git a/package.json b/package.json index e48eea7d7..3f145c5f0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "13.1.3", + "version": "13.1.4", "codename": "nasubi", "repository": { "type": "git", diff --git a/packages/backend/src/core/AchievementService.ts b/packages/backend/src/core/AchievementService.ts index 26dd356d3..be763e462 100644 --- a/packages/backend/src/core/AchievementService.ts +++ b/packages/backend/src/core/AchievementService.ts @@ -44,6 +44,7 @@ const ACHIEVEMENT_TYPES = [ 'loggedInOnNewYearsDay', 'noteClipped1', 'noteFavorited1', + 'myNoteFavorited1', 'profileFilled', 'markedAsCat', 'following1', @@ -94,7 +95,7 @@ export class AchievementService { @bindThis public async create( userId: User['id'], - type: string, + type: typeof ACHIEVEMENT_TYPES[number], ): Promise { if (!ACHIEVEMENT_TYPES.includes(type)) return; diff --git a/packages/backend/src/server/api/endpoints/notes/favorites/create.ts b/packages/backend/src/server/api/endpoints/notes/favorites/create.ts index acf22a5ad..e423f0f10 100644 --- a/packages/backend/src/server/api/endpoints/notes/favorites/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/favorites/create.ts @@ -6,6 +6,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; import { GetterService } from '@/server/api/GetterService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; +import { AchievementService } from '@/core/AchievementService.js'; export const meta = { tags: ['notes', 'favorites'], @@ -51,6 +52,7 @@ export default class extends Endpoint { private idService: IdService, private getterService: GetterService, + private achievementService: AchievementService, ) { super(meta, paramDef, async (ps, me) => { // Get favoritee @@ -76,6 +78,10 @@ export default class extends Endpoint { noteId: note.id, userId: me.id, }); + + if (note.userHost == null) { + this.achievementService.create(note.userId, 'myNoteFavorited1'); + } }); } } diff --git a/packages/backend/src/server/web/boot.js b/packages/backend/src/server/web/boot.js index a4513696a..3d6dabe57 100644 --- a/packages/backend/src/server/web/boot.js +++ b/packages/backend/src/server/web/boot.js @@ -22,18 +22,13 @@ renderError('SOMETHING_HAPPENED_IN_PROMISE', e); }; - const v = localStorage.getItem('v') || VERSION; - let forceError = localStorage.getItem('forceError'); if (forceError != null) { renderError('FORCED_ERROR', 'This error is forced by having forceError in local storage.') } //#region Detect language & fetch translations - const localeVersion = localStorage.getItem('localeVersion'); - const localeOutdated = (localeVersion == null || localeVersion !== v); - - if (!localStorage.hasOwnProperty('locale') || localeOutdated) { + if (!localStorage.hasOwnProperty('locale')) { const supportedLangs = LANGS; let lang = localStorage.getItem('lang'); if (lang == null || !supportedLangs.includes(lang)) { @@ -47,13 +42,31 @@ } } - const res = await window.fetch(`/assets/locales/${lang}.${v}.json`); - if (res.status === 200) { + const metaRes = await window.fetch('/api/meta', { + method: 'POST', + body: JSON.stringify({}), + credentials: 'omit', + cache: 'no-cache', + headers: { + 'Content-Type': 'application/json', + }, + }); + if (metaRes.status !== 200) { + renderError('META_FETCH'); + return; + } + const meta = await res.json(); + const v = meta.version; + if (v == null) { + renderError('META_FETCH_V'); + return; + } + const localRes = await window.fetch(`/assets/locales/${lang}.${v}.json`); + if (localRes.status === 200) { localStorage.setItem('lang', lang); - localStorage.setItem('locale', await res.text()); + localStorage.setItem('locale', await localRes.text()); localStorage.setItem('localeVersion', v); } else { - await checkUpdate(); renderError('LOCALE_FETCH'); return; } @@ -64,7 +77,6 @@ function importAppScript() { import(`/vite/${CLIENT_ENTRY}`) .catch(async e => { - await checkUpdate(); console.error(e); renderError('APP_IMPORT', e); }); @@ -291,48 +303,4 @@ } `) } - - // eslint-disable-next-line no-inner-declarations - async function checkUpdate() { - try { - const res = await window.fetch('/api/meta', { - method: 'POST', - cache: 'no-cache', - body: '{}', - headers: { - 'Content-Type': 'application/json', - }, - }); - - const meta = await res.json(); - - if (meta.version == null) { - throw new Error('failed to fetch instance metadata'); - } - - if (meta.version != v) { - localStorage.setItem('v', meta.version); - refresh(); - } - } catch (e) { - console.error(e); - renderError('UPDATE_CHECK', e); - throw e; - } - } - - // eslint-disable-next-line no-inner-declarations - function refresh() { - // Clear cache (service worker) - try { - navigator.serviceWorker.controller.postMessage('clear'); - navigator.serviceWorker.getRegistrations().then(registrations => { - registrations.forEach(registration => registration.unregister()); - }); - } catch (e) { - console.error(e); - } - - location.reload(); - } })(); diff --git a/packages/frontend/src/config.ts b/packages/frontend/src/config.ts index 4b084d365..073b21a0a 100644 --- a/packages/frontend/src/config.ts +++ b/packages/frontend/src/config.ts @@ -10,8 +10,12 @@ export const apiUrl = url + '/api'; export const wsUrl = url.replace('http://', 'ws://').replace('https://', 'wss://') + '/streaming'; export const lang = miLocalStorage.getItem('lang'); export const langs = _LANGS_; -export const locale = JSON.parse(miLocalStorage.getItem('locale')); +export let locale = JSON.parse(miLocalStorage.getItem('locale')); export const version = _VERSION_; export const instanceName = siteName === 'Misskey' ? host : siteName; export const ui = miLocalStorage.getItem('ui'); export const debug = miLocalStorage.getItem('debug') === 'true'; + +export function updateLocale(newLocale) { + locale = newLocale; +} diff --git a/packages/frontend/src/i18n.ts b/packages/frontend/src/i18n.ts index 31e066960..220c6210c 100644 --- a/packages/frontend/src/i18n.ts +++ b/packages/frontend/src/i18n.ts @@ -3,3 +3,7 @@ import { locale } from '@/config'; import { I18n } from '@/scripts/i18n'; export const i18n = markRaw(new I18n(locale)); + +export function updateI18n(newLocale) { + i18n.ts = newLocale; +} diff --git a/packages/frontend/src/init.ts b/packages/frontend/src/init.ts index 079003ee8..36897545e 100644 --- a/packages/frontend/src/init.ts +++ b/packages/frontend/src/init.ts @@ -25,10 +25,10 @@ import JSON5 from 'json5'; import widgets from '@/widgets'; import directives from '@/directives'; import components from '@/components'; -import { version, ui, lang, host } from '@/config'; +import { version, ui, lang, host, updateLocale } from '@/config'; import { applyTheme } from '@/scripts/theme'; import { isDeviceDarkmode } from '@/scripts/is-device-darkmode'; -import { i18n } from '@/i18n'; +import { i18n, updateI18n } from '@/i18n'; import { confirm, alert, post, popup, toast } from '@/os'; import { stream } from '@/stream'; import * as sound from '@/scripts/sound'; @@ -87,9 +87,12 @@ import { fetchCustomEmojis } from './custom-emojis'; if (localeOutdated) { const res = await window.fetch(`/assets/locales/${lang}.${version}.json`); if (res.status === 200) { - miLocalStorage.setItem('locale', await res.text()); + const newLocale = await res.text(); + const parsedNewLocale = JSON.parse(newLocale); + miLocalStorage.setItem('locale', newLocale); miLocalStorage.setItem('localeVersion', version); - location.reload(); + updateLocale(parsedNewLocale); + updateI18n(parsedNewLocale); } } //#endregion diff --git a/packages/frontend/src/scripts/achievements.ts b/packages/frontend/src/scripts/achievements.ts index c97358e88..f511fce3e 100644 --- a/packages/frontend/src/scripts/achievements.ts +++ b/packages/frontend/src/scripts/achievements.ts @@ -40,6 +40,7 @@ export const ACHIEVEMENT_TYPES = [ 'loggedInOnNewYearsDay', 'noteClipped1', 'noteFavorited1', + 'myNoteFavorited1', 'profileFilled', 'markedAsCat', 'following1', @@ -240,6 +241,11 @@ export const ACHIEVEMENT_BADGES = { bg: null, frame: 'bronze', }, + 'myNoteFavorited1': { + img: '/fluent-emoji/1f320.png', + bg: null, + frame: 'silver', + }, 'profileFilled': { img: '/fluent-emoji/1f44c.png', bg: 'linear-gradient(0deg, rgb(187 183 59), rgb(255 143 77))',