mirror of
https://github.com/plankanban/planka.git
synced 2025-07-19 05:09:43 +02:00
feat: Languages with country codes
This commit is contained in:
parent
e9b4a4adfc
commit
9dc38932fb
83 changed files with 211 additions and 99 deletions
24
client/package-lock.json
generated
24
client/package-lock.json
generated
|
@ -12,7 +12,7 @@
|
|||
"dequal": "^2.0.3",
|
||||
"easymde": "^2.18.0",
|
||||
"history": "^5.3.0",
|
||||
"i18next": "^23.11.5",
|
||||
"i18next": "^23.12.2",
|
||||
"i18next-browser-languagedetector": "^8.0.0",
|
||||
"initials": "^3.1.2",
|
||||
"js-cookie": "^3.0.5",
|
||||
|
@ -30,7 +30,7 @@
|
|||
"react-datepicker": "^4.25.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-dropzone": "^14.2.3",
|
||||
"react-i18next": "^14.1.2",
|
||||
"react-i18next": "^15.0.0",
|
||||
"react-input-mask": "^2.0.4",
|
||||
"react-markdown": "^8.0.7",
|
||||
"react-photoswipe-gallery": "^2.2.7",
|
||||
|
@ -2007,9 +2007,9 @@
|
|||
"integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA=="
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.24.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.6.tgz",
|
||||
"integrity": "sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw==",
|
||||
"version": "7.24.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz",
|
||||
"integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==",
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.14.0"
|
||||
},
|
||||
|
@ -11975,9 +11975,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/i18next": {
|
||||
"version": "23.11.5",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-23.11.5.tgz",
|
||||
"integrity": "sha512-41pvpVbW9rhZPk5xjCX2TPJi2861LEig/YRhUkY+1FQ2IQPS0bKUDYnEqY8XPPbB48h1uIwLnP9iiEfuSl20CA==",
|
||||
"version": "23.12.2",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-23.12.2.tgz",
|
||||
"integrity": "sha512-XIeh5V+bi8SJSWGL3jqbTEBW5oD6rbP5L+E7dVQh1MNTxxYef0x15rhJVcRb7oiuq4jLtgy2SD8eFlf6P2cmqg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
|
@ -22084,11 +22084,11 @@
|
|||
"integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="
|
||||
},
|
||||
"node_modules/react-i18next": {
|
||||
"version": "14.1.2",
|
||||
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.1.2.tgz",
|
||||
"integrity": "sha512-FSIcJy6oauJbGEXfhUgVeLzvWBhIBIS+/9c6Lj4niwKZyGaGb4V4vUbATXSlsHJDXXB+ociNxqFNiFuV1gmoqg==",
|
||||
"version": "15.0.0",
|
||||
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.0.0.tgz",
|
||||
"integrity": "sha512-2O3IgF4zivg57Q6p6i+ChDgJ371IDcEWbuWC6gvoh5NbkDMs0Q+O7RPr4v61+Se32E0V+LmtwePAeqWZW0bi6g==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@babel/runtime": "^7.24.8",
|
||||
"html-parse-stringify": "^3.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
"dequal": "^2.0.3",
|
||||
"easymde": "^2.18.0",
|
||||
"history": "^5.3.0",
|
||||
"i18next": "^23.11.5",
|
||||
"i18next": "^23.12.2",
|
||||
"i18next-browser-languagedetector": "^8.0.0",
|
||||
"initials": "^3.1.2",
|
||||
"js-cookie": "^3.0.5",
|
||||
|
@ -83,7 +83,7 @@
|
|||
"react-datepicker": "^4.25.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-dropzone": "^14.2.3",
|
||||
"react-i18next": "^14.1.2",
|
||||
"react-i18next": "^15.0.0",
|
||||
"react-input-mask": "^2.0.4",
|
||||
"react-markdown": "^8.0.7",
|
||||
"react-photoswipe-gallery": "^2.2.7",
|
||||
|
|
|
@ -58,9 +58,9 @@ i18n
|
|||
.use(initReactI18next)
|
||||
.init({
|
||||
resources: embeddedLocales,
|
||||
fallbackLng: 'en',
|
||||
fallbackLng: 'en-US',
|
||||
supportedLngs: languages,
|
||||
load: 'languageOnly',
|
||||
load: 'currentOnly',
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
format(value, format, language) {
|
||||
|
@ -80,7 +80,7 @@ i18n
|
|||
});
|
||||
|
||||
i18n.loadCoreLocale = async (language = i18n.resolvedLanguage) => {
|
||||
if (language === 'en') {
|
||||
if (language === i18n.options.fallbackLng[0]) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'bg',
|
||||
language: 'bg-BG',
|
||||
country: 'bg',
|
||||
name: 'Български',
|
||||
embeddedLocale: login,
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'cs',
|
||||
language: 'cs-CZ',
|
||||
country: 'cz',
|
||||
name: 'Čeština',
|
||||
embeddedLocale: login,
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'da',
|
||||
language: 'da-DK',
|
||||
country: 'dk',
|
||||
name: 'Dansk',
|
||||
embeddedLocale: login,
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'de',
|
||||
language: 'de-DE',
|
||||
country: 'de',
|
||||
name: 'Deutsch',
|
||||
embeddedLocale: login,
|
|
@ -4,8 +4,8 @@ import login from './login';
|
|||
import core from './core';
|
||||
|
||||
export default {
|
||||
language: 'en',
|
||||
country: 'gb',
|
||||
language: 'en-US',
|
||||
country: 'us',
|
||||
name: 'English',
|
||||
embeddedLocale: merge(login, core),
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'es',
|
||||
language: 'es-ES',
|
||||
country: 'es',
|
||||
name: 'Español',
|
||||
embeddedLocale: login,
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'fa',
|
||||
language: 'fa-IR',
|
||||
country: 'ir',
|
||||
name: 'فارسی',
|
||||
embeddedLocale: login,
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'fr',
|
||||
language: 'fr-FR',
|
||||
country: 'fr',
|
||||
name: 'Français',
|
||||
embeddedLocale: login,
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'hu',
|
||||
language: 'hu-HU',
|
||||
country: 'hu',
|
||||
name: 'Magyar',
|
||||
embeddedLocale: login,
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'id',
|
||||
language: 'id-ID',
|
||||
country: 'id',
|
||||
name: 'Bahasa Indonesia',
|
||||
embeddedLocale: login,
|
|
@ -1,53 +1,53 @@
|
|||
import bg from './bg';
|
||||
import cs from './cs';
|
||||
import da from './da';
|
||||
import de from './de';
|
||||
import en from './en';
|
||||
import es from './es';
|
||||
import fa from './fa';
|
||||
import fr from './fr';
|
||||
import hu from './hu';
|
||||
import id from './id';
|
||||
import it from './it';
|
||||
import ja from './ja';
|
||||
import ko from './ko';
|
||||
import nl from './nl';
|
||||
import pl from './pl';
|
||||
import pt from './pt';
|
||||
import ro from './ro';
|
||||
import ru from './ru';
|
||||
import sk from './sk';
|
||||
import sv from './sv';
|
||||
import tr from './tr';
|
||||
import ua from './ua';
|
||||
import uz from './uz';
|
||||
import zh from './zh';
|
||||
import bgBG from './bg-BG';
|
||||
import csCZ from './cs-CZ';
|
||||
import daDK from './da-DK';
|
||||
import deDE from './de-DE';
|
||||
import enUS from './en-US';
|
||||
import esES from './es-ES';
|
||||
import faIR from './fa-IR';
|
||||
import frFR from './fr-FR';
|
||||
import huHU from './hu-HU';
|
||||
import idID from './id-ID';
|
||||
import itIT from './it-IT';
|
||||
import jaJP from './ja-JP';
|
||||
import koKR from './ko-KR';
|
||||
import nlNL from './nl-NL';
|
||||
import plPL from './pl-PL';
|
||||
import ptBR from './pt-BR';
|
||||
import roRO from './ro-RO';
|
||||
import ruRU from './ru-RU';
|
||||
import skSK from './sk-SK';
|
||||
import svSE from './sv-SE';
|
||||
import trTR from './tr-TR';
|
||||
import ukUA from './uk-UA';
|
||||
import uzUZ from './uz-UZ';
|
||||
import zhCN from './zh-CN';
|
||||
|
||||
const locales = [
|
||||
bg,
|
||||
cs,
|
||||
da,
|
||||
de,
|
||||
en,
|
||||
es,
|
||||
fa,
|
||||
fr,
|
||||
hu,
|
||||
id,
|
||||
it,
|
||||
ja,
|
||||
ko,
|
||||
nl,
|
||||
pl,
|
||||
pt,
|
||||
ro,
|
||||
ru,
|
||||
sk,
|
||||
sv,
|
||||
tr,
|
||||
ua,
|
||||
uz,
|
||||
zh,
|
||||
bgBG,
|
||||
csCZ,
|
||||
daDK,
|
||||
deDE,
|
||||
enUS,
|
||||
esES,
|
||||
faIR,
|
||||
frFR,
|
||||
huHU,
|
||||
idID,
|
||||
itIT,
|
||||
jaJP,
|
||||
koKR,
|
||||
nlNL,
|
||||
plPL,
|
||||
ptBR,
|
||||
roRO,
|
||||
ruRU,
|
||||
skSK,
|
||||
svSE,
|
||||
trTR,
|
||||
ukUA,
|
||||
uzUZ,
|
||||
zhCN,
|
||||
];
|
||||
|
||||
export default locales;
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
import dateFns from 'date-fns/locale/it';
|
||||
|
||||
export default {
|
||||
dateFns,
|
||||
|
||||
format: {
|
||||
date: 'd/M/yyyy',
|
||||
time: 'p',
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'it',
|
||||
language: 'it-IT',
|
||||
country: 'it',
|
||||
name: 'Italiano',
|
||||
embeddedLocale: login,
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'ja',
|
||||
language: 'ja-JP',
|
||||
country: 'jp',
|
||||
name: '日本語',
|
||||
embeddedLocale: login,
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'ko',
|
||||
language: 'ko-KR',
|
||||
country: 'kr',
|
||||
name: '한국어',
|
||||
embeddedLocale: login,
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'nl',
|
||||
language: 'nl-NL',
|
||||
country: 'nl',
|
||||
name: 'Nederlands',
|
||||
embeddedLocale: login,
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'pl',
|
||||
language: 'pl-PL',
|
||||
country: 'pl',
|
||||
name: 'Polski',
|
||||
embeddedLocale: login,
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'pt',
|
||||
language: 'pt-BR',
|
||||
country: 'br',
|
||||
name: 'Português',
|
||||
embeddedLocale: login,
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'ro',
|
||||
language: 'ro-RO',
|
||||
country: 'ro',
|
||||
name: 'Română',
|
||||
embeddedLocale: login,
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'ru',
|
||||
language: 'ru-RU',
|
||||
country: 'ru',
|
||||
name: 'Русский',
|
||||
embeddedLocale: login,
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'sk',
|
||||
language: 'sk-SK',
|
||||
country: 'sk',
|
||||
name: 'Slovenčina',
|
||||
embeddedLocale: login,
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'sv',
|
||||
language: 'sv-SE',
|
||||
country: 'se',
|
||||
name: 'Svenska',
|
||||
embeddedLocale: login,
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'tr',
|
||||
language: 'tr-TR',
|
||||
country: 'tr',
|
||||
name: 'Türkçe',
|
||||
embeddedLocale: login,
|
|
@ -1,4 +1,8 @@
|
|||
import dateFns from 'date-fns/locale/uk';
|
||||
|
||||
export default {
|
||||
dateFns,
|
||||
|
||||
format: {
|
||||
date: 'd/M/yyyy',
|
||||
time: 'p',
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'ua',
|
||||
language: 'uk-UA',
|
||||
country: 'ua',
|
||||
name: 'Українська',
|
||||
embeddedLocale: login,
|
|
@ -1,4 +1,8 @@
|
|||
import dateFns from 'date-fns/locale/uz';
|
||||
|
||||
export default {
|
||||
dateFns,
|
||||
|
||||
format: {
|
||||
date: 'M/d/yyyy',
|
||||
time: 'p',
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'uz',
|
||||
language: 'uz-UZ',
|
||||
country: 'uz',
|
||||
name: "O'zbek",
|
||||
embeddedLocale: login,
|
|
@ -1,4 +1,8 @@
|
|||
import dateFns from 'date-fns/locale/zh-CN';
|
||||
|
||||
export default {
|
||||
dateFns,
|
||||
|
||||
format: {
|
||||
date: 'M/d/yyyy',
|
||||
time: 'p',
|
|
@ -1,7 +1,7 @@
|
|||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'zh',
|
||||
language: 'zh-CN',
|
||||
country: 'cn',
|
||||
name: '中文',
|
||||
embeddedLocale: login,
|
|
@ -50,7 +50,7 @@ module.exports = {
|
|||
},
|
||||
language: {
|
||||
type: 'string',
|
||||
isNotEmptyString: true,
|
||||
isIn: User.LANGUAGES,
|
||||
allowNull: true,
|
||||
},
|
||||
subscribeToOwnCards: {
|
||||
|
|
|
@ -36,7 +36,7 @@ module.exports = {
|
|||
},
|
||||
language: {
|
||||
type: 'string',
|
||||
isNotEmptyString: true,
|
||||
isIn: User.LANGUAGES,
|
||||
allowNull: true,
|
||||
},
|
||||
subscribeToOwnCards: {
|
||||
|
|
|
@ -5,11 +5,39 @@
|
|||
* @docs :: https://sailsjs.com/docs/concepts/models-and-orm/models
|
||||
*/
|
||||
|
||||
const LANGUAGES = [
|
||||
'bg-BG',
|
||||
'cs-CZ',
|
||||
'da-DK',
|
||||
'de-DE',
|
||||
'en-US',
|
||||
'es-ES',
|
||||
'fa-IR',
|
||||
'fr-FR',
|
||||
'hu-HU',
|
||||
'id-ID',
|
||||
'it-IT',
|
||||
'ja-JP',
|
||||
'ko-KR',
|
||||
'nl-NL',
|
||||
'pl-PL',
|
||||
'pt-BR',
|
||||
'ro-RO',
|
||||
'ru-RU',
|
||||
'sk-SK',
|
||||
'sv-SE',
|
||||
'tr-TR',
|
||||
'uk-UA',
|
||||
'uz-UZ',
|
||||
'zh-CN',
|
||||
];
|
||||
|
||||
const OIDC = {
|
||||
id: '_oidc',
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
LANGUAGES,
|
||||
OIDC,
|
||||
|
||||
attributes: {
|
||||
|
@ -62,7 +90,7 @@ module.exports = {
|
|||
},
|
||||
language: {
|
||||
type: 'string',
|
||||
isNotEmptyString: true,
|
||||
isIn: LANGUAGES,
|
||||
allowNull: true,
|
||||
},
|
||||
subscribeToOwnCards: {
|
||||
|
|
|
@ -15,7 +15,7 @@ module.exports.up = async (knex) => {
|
|||
const attachments = await knex('attachment');
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (attachment of attachments) {
|
||||
for (const attachment of attachments) {
|
||||
if (attachment.is_image) {
|
||||
const image = sharp(
|
||||
path.join(config.custom.attachmentsPath, attachment.dirname, attachment.filename),
|
||||
|
@ -54,7 +54,7 @@ module.exports.down = async (knex) => {
|
|||
const attachments = await knex('attachment');
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (attachment of attachments) {
|
||||
for (const attachment of attachments) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await knex('attachment')
|
||||
.update({
|
||||
|
|
|
@ -93,7 +93,7 @@ module.exports.up = async (knex) => {
|
|||
const attachments = await knex('attachment').whereNotNull('image');
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (attachment of attachments) {
|
||||
for (const attachment of attachments) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const image = await processAttachmentImage(attachment, config.custom.attachmentsPath);
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ module.exports.up = async (knex) => {
|
|||
const users = await knex('user_account').whereNotNull('avatar');
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (user of users) {
|
||||
for (const user of users) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await processUserAvatar(user, config.custom.userAvatarsPath);
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ module.exports.up = async (knex) => {
|
|||
const projects = await knex('project').whereNotNull('background_image');
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (project of projects) {
|
||||
for (const project of projects) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await processProjectBackgroundImage(project, config.custom.projectBackgroundImagesPath);
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ module.exports.up = async (knex) => {
|
|||
const attachments = await knex('attachment').whereNotNull('image');
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (attachment of attachments) {
|
||||
for (const attachment of attachments) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await processAttachmentImage(attachment, config.custom.attachmentsPath);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
const _ = require('lodash');
|
||||
|
||||
const LANGUAGES = [
|
||||
'bg-BG',
|
||||
'cs-CZ',
|
||||
'da-DK',
|
||||
'de-DE',
|
||||
'en-US',
|
||||
'es-ES',
|
||||
'fa-IR',
|
||||
'fr-FR',
|
||||
'hu-HU',
|
||||
'id-ID',
|
||||
'it-IT',
|
||||
'ja-JP',
|
||||
'ko-KR',
|
||||
'nl-NL',
|
||||
'pl-PL',
|
||||
'pt-BR',
|
||||
'ro-RO',
|
||||
'ru-RU',
|
||||
'sk-SK',
|
||||
'sv-SE',
|
||||
'tr-TR',
|
||||
'uz-UZ',
|
||||
'zh-CN',
|
||||
];
|
||||
|
||||
const LANGUAGE_BY_PREV_LANGUAGE = LANGUAGES.reduce(
|
||||
(result, language) => ({
|
||||
...result,
|
||||
[language.split('-')[0]]: language,
|
||||
}),
|
||||
{},
|
||||
);
|
||||
LANGUAGE_BY_PREV_LANGUAGE.ua = 'uk-UA';
|
||||
|
||||
const PREV_LANGUAGE_BY_LANGUAGE = _.invert(LANGUAGE_BY_PREV_LANGUAGE);
|
||||
|
||||
module.exports.up = async (knex) => {
|
||||
const users = await knex('user_account').whereNotNull('language');
|
||||
const prevLanguages = [...new Set(users.map((user) => user.language))];
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const prevLanguage of prevLanguages) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await knex('user_account')
|
||||
.update({
|
||||
language: LANGUAGE_BY_PREV_LANGUAGE[prevLanguage],
|
||||
})
|
||||
.where('language', prevLanguage);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.down = async (knex) => {
|
||||
const users = await knex('user_account').whereNotNull('language');
|
||||
const languages = [...new Set(users.map((user) => user.language))];
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const language of languages) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await knex('user_account')
|
||||
.update({
|
||||
language: PREV_LANGUAGE_BY_LANGUAGE[language],
|
||||
})
|
||||
.where('language', language);
|
||||
}
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue