mirror of
https://github.com/elyby/accounts-frontend.git
synced 2024-12-27 07:20:23 +05:30
Merge branch 'i18n'
This commit is contained in:
commit
3c897845ab
@ -16,6 +16,6 @@ module.exports = {
|
||||
filePath: 'accounts/site.json',
|
||||
sourceLang: 'en',
|
||||
basePath: `${__dirname}/packages/app/i18n`,
|
||||
minApproved: 80, // Minimal ready percent before translation can be published
|
||||
minTranslated: 80, // Minimal ready percent before translation can be published
|
||||
},
|
||||
};
|
||||
|
@ -45,7 +45,8 @@
|
||||
"build:dll": "babel-node --extensions '.ts,.d.ts' ./packages/scripts/build-dll.ts",
|
||||
"build:serve": "http-server --proxy https://dev.account.ely.by ./build",
|
||||
"sb": "APP_ENV=storybook start-storybook -p 9009 --ci",
|
||||
"sb:build": "APP_ENV=storybook build-storybook"
|
||||
"sb:build": "APP_ENV=storybook build-storybook",
|
||||
"postinstall": "node -e \"try{require('./postinstall.js')}catch(e){}\""
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{json,scss,css,md}": [
|
||||
@ -144,6 +145,7 @@
|
||||
"loader-utils": "^2.0.0",
|
||||
"mini-css-extract-plugin": "^0.9.0",
|
||||
"node-sass": "^4.14.1",
|
||||
"postcss-bidirection": "https://github.com/erickskrauch/postcss-bidirection.git#iss_23",
|
||||
"postcss-import": "^12.0.1",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"postcss-scss": "^2.1.1",
|
||||
|
@ -119,6 +119,7 @@ interface State {
|
||||
formsHeights: Record<PanelId, number>;
|
||||
}
|
||||
|
||||
// TODO: completely broken for RTL languages
|
||||
class PanelTransition extends React.PureComponent<Props, State> {
|
||||
state: State = {
|
||||
contextHeight: 0,
|
||||
|
@ -16,7 +16,6 @@
|
||||
display: block;
|
||||
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
height: 3px;
|
||||
width: 40px;
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
.accountSwitcher {
|
||||
background: $black;
|
||||
text-align: left;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
$border: 1px solid lighter($black);
|
||||
@ -37,12 +37,12 @@ $border: 1px solid lighter($black);
|
||||
|
||||
.accountAvatar {
|
||||
font-size: 35px;
|
||||
margin-right: 15px;
|
||||
margin-inline-end: 15px;
|
||||
}
|
||||
|
||||
.accountInfo {
|
||||
flex-grow: 1;
|
||||
margin-right: 15px;
|
||||
margin-inline-end: 15px;
|
||||
min-width: 0; // Fix for text-overflow. See https://stackoverflow.com/a/40612184
|
||||
}
|
||||
|
||||
@ -76,17 +76,25 @@ $border: 1px solid lighter($black);
|
||||
composes: arrowRight from '~app/components/ui/icons.scss';
|
||||
|
||||
position: relative;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
|
||||
font-size: 24px;
|
||||
color: #4e4e4e;
|
||||
line-height: 35px;
|
||||
|
||||
transition: color 0.25s, inset-inline-start 0.5s;
|
||||
// TODO: right now transition property doesn't support the bidirectional value.
|
||||
// See https://github.com/gasolin/postcss-bidirection/issues/25.
|
||||
// noinspection CssOverwrittenProperties Graceful degradation
|
||||
transition: color 0.25s, left 0.5s;
|
||||
|
||||
html[dir='rtl'] & {
|
||||
transition: color 0.25s, right 0.5s;
|
||||
}
|
||||
|
||||
.item:hover & {
|
||||
color: #aaa;
|
||||
left: 5px;
|
||||
inset-inline-start: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
position: relative;
|
||||
bottom: 1px;
|
||||
padding-left: 3px;
|
||||
padding-inline-start: 3px;
|
||||
|
||||
color: #666666;
|
||||
font-size: 10px;
|
||||
|
@ -4,18 +4,18 @@
|
||||
.authInfo {
|
||||
// Отступы сверху и снизу разные т.к. мы ужимаем высоту линии строки с логином на 2 пикселя и из-за этого теряем отступ снизу
|
||||
padding: 5px 20px 7px;
|
||||
text-align: left;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.authInfoAvatar {
|
||||
$size: 30px;
|
||||
|
||||
float: left;
|
||||
float: start;
|
||||
height: $size;
|
||||
width: $size;
|
||||
font-size: $size;
|
||||
line-height: 1;
|
||||
margin-right: 10px;
|
||||
margin-inline-end: 10px;
|
||||
margin-top: 2px;
|
||||
color: #aaa;
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
|
||||
.permissionsContainer {
|
||||
padding: 15px 12px;
|
||||
text-align: left;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.permissionsTitle {
|
||||
@ -57,7 +57,7 @@
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
padding-bottom: 4px;
|
||||
padding-left: 17px;
|
||||
padding-inline-start: 17px;
|
||||
position: relative;
|
||||
|
||||
&:last-of-type {
|
||||
@ -71,7 +71,7 @@
|
||||
line-height: 9px;
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
left: -4px;
|
||||
inset-inline-start: -4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@
|
||||
width: 50%;
|
||||
|
||||
&:first-of-type {
|
||||
margin-right: $popupPadding;
|
||||
margin-inline-end: $popupPadding;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,7 +160,7 @@
|
||||
composes: arrowRight from '~app/components/ui/icons.scss';
|
||||
|
||||
position: relative;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
|
||||
font-size: 28px;
|
||||
color: #ebe8e1;
|
||||
@ -173,7 +173,11 @@
|
||||
|
||||
.appExpanded & {
|
||||
color: #777;
|
||||
transform: rotate(360deg) !important; // Prevent it from hover rotating
|
||||
transform: rotate(360deg)!important; // Prevent it from hover rotating
|
||||
|
||||
html[dir='rtl'] & {
|
||||
transform: rotate(0)!important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,7 +199,7 @@ $appDetailsContainerRightLeftPadding: 30px;
|
||||
.editAppLink {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 0;
|
||||
inset-inline-end: 0;
|
||||
|
||||
font-size: 12px;
|
||||
color: #9a9a9a;
|
||||
@ -221,17 +225,19 @@ $appDetailsContainerRightLeftPadding: 30px;
|
||||
}
|
||||
|
||||
.appActionButton {
|
||||
margin: 0 10px 10px 0;
|
||||
margin-inline-end: 10px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
&:last-of-type {
|
||||
margin-right: 0;
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.appActionContainer {
|
||||
position: absolute;
|
||||
width: calc(100% - #{$appDetailsContainerRightLeftPadding * 2});
|
||||
top: 100%;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
padding: 0 $appDetailsContainerRightLeftPadding;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
@ -244,7 +250,7 @@ $appDetailsContainerRightLeftPadding: 30px;
|
||||
|
||||
.continueActionButtonWrapper {
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
margin-inline-start: 10px;
|
||||
}
|
||||
|
||||
.continueActionLink {
|
||||
|
@ -24,5 +24,5 @@
|
||||
position: relative;
|
||||
bottom: 1px;
|
||||
font-size: 11px;
|
||||
margin-right: 3px;
|
||||
margin-inline-end: 3px;
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
import React, { useState, useEffect, ComponentType } from 'react';
|
||||
import { RawIntlProvider, IntlShape } from 'react-intl';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
|
||||
import { getLangDir } from 'rtl-detect';
|
||||
|
||||
import i18n from 'app/services/i18n';
|
||||
import { useReduxSelector } from 'app/functions';
|
||||
@ -26,7 +29,12 @@ const IntlProvider: ComponentType = ({ children }) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <RawIntlProvider value={intl}>{children}</RawIntlProvider>;
|
||||
return (
|
||||
<RawIntlProvider value={intl}>
|
||||
<Helmet htmlAttributes={{ lang: locale, dir: getLangDir(locale) }} />
|
||||
{children}
|
||||
</RawIntlProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default IntlProvider;
|
||||
|
6
packages/app/components/i18n/flags/ar.svg
Normal file
6
packages/app/components/i18n/flags/ar.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="240" height="180" viewBox="0 0 63.5 47.625">
|
||||
<path fill="#000" d="M0 0h63.5v15.875H0z"/>
|
||||
<path fill="#00783b" d="M0 15.903h63.5v15.875H0z"/>
|
||||
<path fill="#fff" d="M0 31.75h63.5v15.875H0z"/>
|
||||
<path fill="#cc1025" d="m0 0 21.167 23.813A16486.171 16486.171 0 0 1 0 47.624V0z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 343 B |
6
packages/app/components/i18n/flags/udm.svg
Normal file
6
packages/app/components/i18n/flags/udm.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 480">
|
||||
<path d="M0 0h204.8v480H0z"/>
|
||||
<path fill="#D21" d="M435.2 0H640v480H435.2z"/>
|
||||
<path fill="#FFF" d="M204.8 0h230.4v480H204.8z"/>
|
||||
<path fill="#D21" d="M286.667 140L420 273.333H220L353.333 140v200L220 206.667h200L286.667 340V140z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 316 B |
@ -10,6 +10,8 @@ const localeToCountryCode: Record<string, string> = {
|
||||
sr: 'rs',
|
||||
zh: 'cn',
|
||||
cs: 'cz',
|
||||
fil: 'ph',
|
||||
he: 'il',
|
||||
};
|
||||
const SUPPORTED_LANGUAGES: ReadonlyArray<string> = Object.keys(supportedLocales);
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
position: relative;
|
||||
top: 1px;
|
||||
display: inline-block;
|
||||
margin-right: 4px;
|
||||
margin-inline-end: 4px;
|
||||
height: $height;
|
||||
width: $height * 4 / 3;
|
||||
box-shadow: 0 0 1px rgba(#000, 0.2);
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
right: 12px;
|
||||
inset-inline-end: 12px;
|
||||
font-size: 22px;
|
||||
color: #edebe5;
|
||||
pointer-events: none; // Иконка чисто декоративная, так что клик должен проходить сквозь неё
|
||||
@ -94,7 +94,7 @@ $languageListBorderStyle: 1px solid $languageListBorderColor;
|
||||
|
||||
.languageIco {
|
||||
display: inline-block;
|
||||
margin-right: 7px;
|
||||
margin-inline-end: 7px;
|
||||
width: 40px;
|
||||
height: 30px;
|
||||
box-shadow: 0 0 1px rgba(#000, 0.2);
|
||||
@ -129,7 +129,7 @@ $languageListBorderStyle: 1px solid $languageListBorderColor;
|
||||
box-sizing: border-box;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
right: -32px;
|
||||
inset-inline-end: -32px;
|
||||
|
||||
font-size: 10px;
|
||||
line-height: 18px;
|
||||
@ -146,13 +146,13 @@ $languageListBorderStyle: 1px solid $languageListBorderColor;
|
||||
}
|
||||
|
||||
.languageItem:hover & {
|
||||
right: 0;
|
||||
inset-inline-end: 0;
|
||||
}
|
||||
|
||||
.activeLanguageItem & {
|
||||
border-color: $green;
|
||||
background: $green;
|
||||
right: 0;
|
||||
inset-inline-end: 0;
|
||||
|
||||
&:before {
|
||||
opacity: 1;
|
||||
@ -209,7 +209,7 @@ $languageListBorderStyle: 1px solid $languageListBorderColor;
|
||||
|
||||
color: lighter($blue);
|
||||
font-size: 22px;
|
||||
margin-right: 10px;
|
||||
margin-inline-end: 10px;
|
||||
}
|
||||
|
||||
.improveTranslatesContent {
|
||||
|
@ -19,12 +19,12 @@
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
padding-left: 11px;
|
||||
padding-inline-start: 11px;
|
||||
|
||||
&:before {
|
||||
content: '—';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ export default function OsInstruction({ os }: { os: OS }) {
|
||||
<ul className={styles.appList}>
|
||||
{linksByOs[os].featured.map((item) => (
|
||||
<li key={item.label}>
|
||||
<a href={item.link} target="_blank">
|
||||
<a href={item.link} target="_blank" dir="ltr">
|
||||
{item.label}
|
||||
</a>
|
||||
</li>
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
.otherApps {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
inset-inline-end: 0;
|
||||
bottom: 5px;
|
||||
font-size: 10px;
|
||||
|
||||
@ -96,7 +96,7 @@
|
||||
|
||||
.androidActive & {
|
||||
transform: translateX(0);
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
}
|
||||
|
||||
.appleActive &,
|
||||
@ -111,21 +111,33 @@
|
||||
$translateX: -51%;
|
||||
|
||||
transform: translateX($translateX) scale(1);
|
||||
left: 49%;
|
||||
inset-inline-start: 49%;
|
||||
|
||||
html[dir='rtl'] & {
|
||||
transform: translateX(-$translateX) scale(1);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: translateX($translateX) scale(1.1);
|
||||
|
||||
html[dir='rtl'] & {
|
||||
transform: translateX(-$translateX) scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
.appleActive & {
|
||||
transform: translateX(0);
|
||||
left: 0;
|
||||
transform: translateX(0)!important; // override dir='rtl'
|
||||
inset-inline-start: 0;
|
||||
}
|
||||
|
||||
.androidActive &,
|
||||
.windowsActive & {
|
||||
transform: translateX($translateX) scale(0);
|
||||
opacity: 0;
|
||||
|
||||
html[dir='rtl'] & {
|
||||
transform: translateX(-$translateX) scale(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,21 +146,33 @@
|
||||
$translateX: -100%;
|
||||
|
||||
transform: translateX($translateX) scale(1);
|
||||
left: 100%;
|
||||
inset-inline-start: 100%;
|
||||
|
||||
html[dir='rtl'] & {
|
||||
transform: translateX(-$translateX) scale(1);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: translateX($translateX) scale(1.1);
|
||||
|
||||
html[dir='rtl'] & {
|
||||
transform: translateX(-$translateX) scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
.windowsActive & {
|
||||
transform: translateX(0);
|
||||
left: 0;
|
||||
transform: translateX(0)!important; // override dir='rtl'
|
||||
inset-inline-start: 0;
|
||||
}
|
||||
|
||||
.appleActive &,
|
||||
.androidActive & {
|
||||
transform: translateX($translateX) scale(0);
|
||||
opacity: 0;
|
||||
|
||||
html[dir='rtl'] & {
|
||||
transform: translateX(-$translateX) scale(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,8 +190,8 @@
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin: 15px;
|
||||
margin-left: 30%;
|
||||
padding-left: 15px;
|
||||
margin-inline-start: 30%;
|
||||
padding-inline-start: 15px;
|
||||
padding-bottom: 15px;
|
||||
min-height: $boxHeight;
|
||||
}
|
||||
@ -212,7 +236,7 @@
|
||||
.osName {
|
||||
font-family: $font-family-title;
|
||||
font-size: 16px;
|
||||
margin-left: 10px;
|
||||
margin-inline-start: 10px;
|
||||
}
|
||||
|
||||
@mixin commonNonActiveTile() {
|
||||
|
@ -16,8 +16,8 @@ $maxQrCodeSize: 242px;
|
||||
}
|
||||
|
||||
.or {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
position: absolute; // Use absolute positioning to put an element between margin
|
||||
inset-inline-start: 0; // TODO: doesn't have any effect. Probably can be removed
|
||||
width: 100%;
|
||||
margin-top: -18px;
|
||||
|
||||
|
@ -13,7 +13,8 @@ $formColumnWidth: 416px;
|
||||
}
|
||||
|
||||
.descriptionColumn {
|
||||
padding: 12px 20px 0 0;
|
||||
padding-top: 12px;
|
||||
padding-inline-end: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@ -97,7 +98,8 @@ $formColumnWidth: 416px;
|
||||
}
|
||||
|
||||
.paramMessage {
|
||||
padding: 10px 40px 0 0;
|
||||
padding-top: 10px;
|
||||
padding-inline-end: 40px;
|
||||
|
||||
color: $red;
|
||||
font-size: 11px;
|
||||
@ -168,7 +170,7 @@ $formColumnWidth: 416px;
|
||||
}
|
||||
|
||||
.paramEditIcon {
|
||||
margin-left: 5px;
|
||||
margin-inline-start: 5px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
.backButton {
|
||||
position: absolute;
|
||||
left: -60px;
|
||||
inset-inline-start: -60px;
|
||||
top: 15px;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
@ -60,7 +60,6 @@
|
||||
display: block;
|
||||
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
height: 3px;
|
||||
width: 86px;
|
||||
@ -110,7 +109,7 @@
|
||||
|
||||
.backButton {
|
||||
top: 29px;
|
||||
left: 27px;
|
||||
inset-inline-start: 27px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: auto;
|
||||
|
@ -29,7 +29,8 @@
|
||||
}
|
||||
|
||||
.iconWrapper {
|
||||
margin: 4px 12px 0 0;
|
||||
margin-top: 4px;
|
||||
margin-inline-end: 12px;
|
||||
}
|
||||
|
||||
.dbIcon {
|
||||
@ -68,14 +69,15 @@
|
||||
font-family: $font-family-title;
|
||||
font-size: 14px;
|
||||
color: #9a9a9a;
|
||||
margin: 0 0 5px 1px; // Add 1px from the left to make icon look visually aligned with texts
|
||||
margin-bottom: 5px;
|
||||
margin-inline-start: 1px; // Add 1px from the left to make icon look visually aligned with texts
|
||||
}
|
||||
|
||||
.githubIcon {
|
||||
composes: github from '~app/components/ui/icons.scss';
|
||||
|
||||
font-size: 12px;
|
||||
margin-right: 2px;
|
||||
margin-inline-end: 2px;
|
||||
position: relative;
|
||||
bottom: 1px;
|
||||
}
|
||||
|
@ -1,20 +0,0 @@
|
||||
.horizontalGroup {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.item {
|
||||
// TODO: in some cases we do not need overflow hidden
|
||||
// probably, it is better to create a separate class for children, that will
|
||||
// enable overflow hidden and ellipsis
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
|
||||
$borderConfig: 1px solid rgba(#fff, 0.15);
|
||||
|
||||
border-left: $borderConfig;
|
||||
|
||||
&:last-child {
|
||||
border-right: $borderConfig;
|
||||
}
|
||||
}
|
@ -1,29 +1,29 @@
|
||||
import React from 'react';
|
||||
import React, { ReactNode } from 'react';
|
||||
import { MessageDescriptor } from 'react-intl';
|
||||
|
||||
import i18n from 'app/services/i18n';
|
||||
|
||||
function isMessageDescriptor(value: any): value is MessageDescriptor {
|
||||
return typeof value === 'object' && value.id;
|
||||
}
|
||||
|
||||
export default class FormComponent<P, S = {}> extends React.Component<P, S> {
|
||||
/**
|
||||
* Formats message resolving intl translations
|
||||
*
|
||||
* @param {string|object} message - message string, or intl message descriptor with an `id` field
|
||||
*
|
||||
* @deprecated
|
||||
* @returns {string}
|
||||
*/
|
||||
formatMessage(message: string | MessageDescriptor): string {
|
||||
if (!message) {
|
||||
throw new Error('A message is required');
|
||||
formatMessage<T extends ReactNode | MessageDescriptor>(message: T): T extends MessageDescriptor ? string : T {
|
||||
if (isMessageDescriptor(message)) {
|
||||
// @ts-ignore
|
||||
return i18n.getIntl().formatMessage(message);
|
||||
}
|
||||
|
||||
if (typeof message === 'string') {
|
||||
return message;
|
||||
}
|
||||
|
||||
if (!message.id) {
|
||||
throw new Error(`Invalid message format: ${JSON.stringify(message)}`);
|
||||
}
|
||||
|
||||
return i18n.getIntl().formatMessage(message);
|
||||
// @ts-ignore
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { ReactNode } from 'react';
|
||||
import { MessageDescriptor } from 'react-intl';
|
||||
import clsx from 'clsx';
|
||||
import { uniqueId, omit } from 'app/functions';
|
||||
@ -17,7 +17,7 @@ export default class Input extends FormInputComponent<
|
||||
color: Color;
|
||||
center: boolean;
|
||||
disabled: boolean;
|
||||
label?: string | MessageDescriptor;
|
||||
label?: ReactNode | MessageDescriptor;
|
||||
placeholder?: string | MessageDescriptor;
|
||||
icon?: string;
|
||||
copy?: boolean;
|
||||
|
@ -25,8 +25,9 @@ $dropdownPadding: 15px;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
height: 50px;
|
||||
padding-inline-start: $dropdownPadding;
|
||||
// 28px - ширина иконки при заданном размере шрифта
|
||||
padding: 0 ($dropdownPadding * 2 + 28px) 0 $dropdownPadding;
|
||||
padding-inline-end: $dropdownPadding * 2 + 28px;
|
||||
position: relative;
|
||||
|
||||
font-family: $font-family-title;
|
||||
@ -48,6 +49,7 @@ $dropdownPadding: 15px;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.opened {
|
||||
@ -57,18 +59,26 @@ $dropdownPadding: 15px;
|
||||
composes: selecter from '~app/components/ui/icons.scss';
|
||||
|
||||
position: absolute;
|
||||
right: $dropdownPadding;
|
||||
inset-inline-end: $dropdownPadding;
|
||||
top: 16px;
|
||||
font-size: 17px;
|
||||
transition: right 0.3s cubic-bezier(0.23, 1, 0.32, 1); // easeOutQuint
|
||||
transition: inset-inline-end 0.3s cubic-bezier(0.23, 1, 0.32, 1); // easeOutQuint
|
||||
// TODO: right now transition property doesn't support the bidirectional value.
|
||||
// See https://github.com/gasolin/postcss-bidirection/issues/25.
|
||||
// noinspection CssOverwrittenProperties Graceful degradation
|
||||
transition: right 0.3s cubic-bezier(0.23, 1, 0.32, 1);
|
||||
|
||||
html[dir='rtl'] & {
|
||||
transition: left 0.3s cubic-bezier(0.23, 1, 0.32, 1);
|
||||
}
|
||||
|
||||
.dropdown:hover & {
|
||||
right: $dropdownPadding - 5px;
|
||||
inset-inline-end: $dropdownPadding - 5px;
|
||||
}
|
||||
|
||||
.dropdown:active &,
|
||||
.dropdown.opened & {
|
||||
right: $dropdownPadding + 5px;
|
||||
inset-inline-end: $dropdownPadding + 5px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,7 +94,7 @@ $dropdownPadding: 15px;
|
||||
.menu {
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
z-index: 10;
|
||||
|
||||
width: 120%;
|
||||
|
@ -36,7 +36,7 @@
|
||||
composes: formRow;
|
||||
|
||||
.textField {
|
||||
padding-left: 60px;
|
||||
padding-inline-start: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@
|
||||
.textFieldIcon {
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
top: 0;
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
@ -95,7 +95,7 @@
|
||||
|
||||
.copyIcon {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
inset-inline-end: 5px;
|
||||
top: 10px;
|
||||
|
||||
padding: 5px;
|
||||
@ -175,6 +175,7 @@
|
||||
font-family: $font-family-title;
|
||||
color: #666;
|
||||
font-size: 18px;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.fieldError {
|
||||
@ -248,7 +249,7 @@
|
||||
.markableContainer {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
padding-left: 27px;
|
||||
padding-inline-start: 27px;
|
||||
|
||||
font-family: $font-family-title;
|
||||
font-size: 16px;
|
||||
@ -260,7 +261,7 @@
|
||||
.markPosition {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
top: 0;
|
||||
margin: 0;
|
||||
|
||||
|
@ -15,10 +15,30 @@
|
||||
@extend .arrow;
|
||||
|
||||
transform: rotate(270deg);
|
||||
|
||||
html[dir='rtl'] & {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
.arrowLeft {
|
||||
@extend .arrow;
|
||||
|
||||
transform: rotate(90deg);
|
||||
|
||||
html[dir='rtl'] & {
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
}
|
||||
|
||||
html[dir='rtl'] {
|
||||
.brush,
|
||||
.exit,
|
||||
.key,
|
||||
.pencil,
|
||||
.search {
|
||||
&:before {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
.loader-overlay {
|
||||
direction: ltr;
|
||||
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
|
@ -77,8 +77,8 @@ class SlideMotion extends React.PureComponent<Props, State> {
|
||||
<div
|
||||
className={styles.container}
|
||||
style={{
|
||||
WebkitTransform: `translateX(-${interpolatingStyle.transform}%)`,
|
||||
transform: `translateX(-${interpolatingStyle.transform}%)`,
|
||||
// @ts-ignore see https://stackoverflow.com/a/52013197/5184751
|
||||
'--transition-progress': `${interpolatingStyle.transform}%`,
|
||||
}}
|
||||
>
|
||||
{React.Children.map(children, (child, index) => (
|
||||
|
@ -1,5 +1,11 @@
|
||||
.container {
|
||||
white-space: nowrap;
|
||||
transform: translate(var(--transition-progress));
|
||||
|
||||
html[dir='ltr'] & {
|
||||
// noinspection CssInvalidFunction works fine in a browser (:
|
||||
transform: translate(calc(var(--transition-progress) * -1));
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
|
@ -25,12 +25,12 @@ $headerHeight: 60px;
|
||||
.headerControl {
|
||||
composes: black from '~app/components/ui/buttons.scss';
|
||||
|
||||
float: left;
|
||||
float: start;
|
||||
overflow: hidden;
|
||||
height: $headerHeight - 1px;
|
||||
width: 49px;
|
||||
padding: 0;
|
||||
border-right: 1px solid lighter($black);
|
||||
border-inline-end: 1px solid lighter($black);
|
||||
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
@ -122,7 +122,7 @@ $bodyTopBottomPadding: 15px;
|
||||
composes: close from '~app/components/ui/icons.scss';
|
||||
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
inset-inline-end: 5px;
|
||||
top: 5px;
|
||||
|
||||
font-size: 10px;
|
||||
|
@ -59,7 +59,7 @@ $popupMargin: 20px; // Outer popup margins
|
||||
|
||||
.popup {
|
||||
white-space: normal;
|
||||
text-align: left;
|
||||
text-align: start;
|
||||
|
||||
background: #fff;
|
||||
box-shadow: 0 0 10px rgba(#000, 0.2);
|
||||
@ -95,7 +95,7 @@ $popupMargin: 20px; // Outer popup margins
|
||||
composes: close from '~app/components/ui/icons.scss';
|
||||
|
||||
position: absolute;
|
||||
right: 0;
|
||||
inset-inline-end: 0;
|
||||
top: 0;
|
||||
padding: 15px;
|
||||
cursor: pointer;
|
||||
@ -122,6 +122,10 @@ $popupMargin: 20px; // Outer popup margins
|
||||
opacity: 0;
|
||||
transform: translate(100%);
|
||||
transition: 0s;
|
||||
|
||||
html[dir='rtl'] & {
|
||||
transform: translate(-100%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@
|
||||
|
||||
position: absolute;
|
||||
top: 0.16em;
|
||||
left: -0.145em;
|
||||
inset-inline-start: -0.145em;
|
||||
font-size: 0.7em;
|
||||
color: rgba($red, 0.75);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
.step {
|
||||
position: relative;
|
||||
text-align: right;
|
||||
text-align: end;
|
||||
width: 100%;
|
||||
|
||||
height: 4px;
|
||||
@ -24,8 +24,8 @@
|
||||
|
||||
position: absolute;
|
||||
height: 4px;
|
||||
left: 0;
|
||||
right: 100%;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: 100%;
|
||||
top: 50%;
|
||||
margin-top: -2px;
|
||||
|
||||
@ -53,7 +53,7 @@
|
||||
|
||||
.activeStep {
|
||||
&:before {
|
||||
right: 0;
|
||||
inset-inline-end: 0;
|
||||
transition-delay: unset;
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ const AccountSwitcher: ComponentType<Props> = ({
|
||||
<div className={clsx(styles.accountSwitcher)} data-testid="account-switcher">
|
||||
<div className={styles.item} data-testid="active-account">
|
||||
<PseudoAvatar className={styles.activeAccountIcon} />
|
||||
<div className={styles.activeAccountInfo}>
|
||||
<div>
|
||||
<div className={styles.activeAccountUsername}>{activeAccount.username}</div>
|
||||
<div className={clsx(styles.accountEmail, styles.activeAccountEmail)}>{activeAccount.email}</div>
|
||||
<div className={styles.links}>
|
||||
@ -81,16 +81,16 @@ const AccountSwitcher: ComponentType<Props> = ({
|
||||
>
|
||||
<PseudoAvatar index={index + 1} deleted={account.isDeleted} className={styles.accountIcon} />
|
||||
|
||||
<div className={styles.accountInfo}>
|
||||
<div className={styles.accountUsername}>{account.username}</div>
|
||||
<div className={styles.accountEmail}>{account.email}</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={styles.logoutIcon}
|
||||
data-testid="logout-account"
|
||||
onClick={onAccountRemoveCallback(account)}
|
||||
/>
|
||||
|
||||
<div className={styles.accountInfo}>
|
||||
<div className={styles.accountUsername}>{account.username}</div>
|
||||
<div className={styles.accountEmail}>{account.email}</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<Link to="/login" onClick={onLoginClick}>
|
||||
|
@ -8,8 +8,6 @@ $bodyLeftRightPadding: 20px;
|
||||
$lightBorderColor: #eee;
|
||||
|
||||
.accountSwitcher {
|
||||
text-align: left;
|
||||
|
||||
background: #fff;
|
||||
color: #444;
|
||||
min-width: 205px;
|
||||
@ -20,9 +18,6 @@ $lightBorderColor: #eee;
|
||||
border-bottom: 7px solid darker($green);
|
||||
}
|
||||
|
||||
.accountInfo {
|
||||
}
|
||||
|
||||
.accountUsername,
|
||||
.accountEmail {
|
||||
overflow: hidden;
|
||||
@ -30,6 +25,7 @@ $lightBorderColor: #eee;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
padding: 15px;
|
||||
border-bottom: 1px solid $lightBorderColor;
|
||||
}
|
||||
@ -50,8 +46,7 @@ $lightBorderColor: #eee;
|
||||
.accountIcon {
|
||||
font-size: 27px;
|
||||
width: 20px;
|
||||
text-align: center;
|
||||
float: left;
|
||||
margin-inline-end: 9px;
|
||||
}
|
||||
|
||||
.activeAccountIcon {
|
||||
@ -60,10 +55,6 @@ $lightBorderColor: #eee;
|
||||
font-size: 40px;
|
||||
}
|
||||
|
||||
.activeAccountInfo {
|
||||
margin-left: 29px;
|
||||
}
|
||||
|
||||
.activeAccountUsername {
|
||||
font-family: $font-family-title;
|
||||
font-size: 20px;
|
||||
@ -88,8 +79,7 @@ $lightBorderColor: #eee;
|
||||
}
|
||||
|
||||
.accountInfo {
|
||||
margin-left: 29px;
|
||||
margin-right: 25px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.accountUsername {
|
||||
@ -117,15 +107,16 @@ $lightBorderColor: #eee;
|
||||
color: $green;
|
||||
position: relative;
|
||||
bottom: 1px;
|
||||
margin-right: 3px;
|
||||
margin-inline-end: 3px;
|
||||
}
|
||||
|
||||
.logoutIcon {
|
||||
composes: exit from '~app/components/ui/icons.scss';
|
||||
|
||||
align-self: center;
|
||||
margin-inline-start: 9px;
|
||||
|
||||
color: #cdcdcd;
|
||||
float: right;
|
||||
line-height: 27px;
|
||||
transition: 0.25s;
|
||||
|
||||
&:hover {
|
||||
|
@ -27,6 +27,10 @@
|
||||
|
||||
.expandIcon {
|
||||
transform: rotate(-180deg);
|
||||
|
||||
html[dir='rtl'] & {
|
||||
transform: rotate(180deg); // Fix spin direction
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,13 +40,13 @@
|
||||
position: relative;
|
||||
bottom: 2px;
|
||||
|
||||
padding-right: 5px;
|
||||
padding-inline-end: 5px;
|
||||
}
|
||||
|
||||
.expandIcon {
|
||||
composes: caret from '~app/components/ui/icons.scss';
|
||||
|
||||
margin-left: 4px;
|
||||
margin-inline-start: 4px;
|
||||
font-size: 6px;
|
||||
color: #ccc;
|
||||
transition: 0.2s;
|
||||
@ -54,7 +58,7 @@
|
||||
.accountSwitcherContainer {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: -2px;
|
||||
inset-inline-end: -2px;
|
||||
cursor: auto;
|
||||
|
||||
display: none;
|
||||
|
@ -30,6 +30,7 @@
|
||||
"redux": "^4.0.5",
|
||||
"redux-localstorage": "^0.4.1",
|
||||
"redux-thunk": "^2.0.0",
|
||||
"rtl-detect": "^1.0.2",
|
||||
"url-search-params-polyfill": "^8.1.0",
|
||||
"webfontloader": "^1.6.26",
|
||||
"whatwg-fetch": "^3.0.0"
|
||||
@ -45,6 +46,7 @@
|
||||
"@types/react-helmet": "^6.0.0",
|
||||
"@types/react-motion": "^0.0.29",
|
||||
"@types/react-transition-group": "^4.2.4",
|
||||
"@types/rtl-detect": "^1.0.0",
|
||||
"@types/webfontloader": "^1.6.30",
|
||||
"@types/webpack-env": "^1.15.2",
|
||||
"utility-types": "^3.10.0"
|
||||
|
@ -26,7 +26,11 @@
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background: white;
|
||||
animation: cubeRotate 1s ease-out infinite;
|
||||
animation: cubeRotateLTR 1s ease-out infinite;
|
||||
|
||||
html[dir='rtl'] & {
|
||||
animation-name: cubeRotateRTL;
|
||||
}
|
||||
}
|
||||
|
||||
.road {
|
||||
@ -34,12 +38,12 @@
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: white;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
bottom: 0;
|
||||
animation: roadStab 1s ease-out infinite;
|
||||
}
|
||||
|
||||
@keyframes cubeRotate {
|
||||
@keyframes cubeRotateLTR {
|
||||
0% {
|
||||
transform: rotate(0deg) translate3D(0, 0, 0);
|
||||
}
|
||||
@ -54,6 +58,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes cubeRotateRTL {
|
||||
0% {
|
||||
transform: rotate(0deg) translate3D(0, 0, 0);
|
||||
}
|
||||
65% {
|
||||
transform: rotate(-45deg) translate3D(0, -13px, 0);
|
||||
}
|
||||
90% {
|
||||
transform: rotate(-70deg) translate3D(0, -8px, 0);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(-90deg) translate3D(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes roadStab {
|
||||
0% {
|
||||
transform: translate3D(0, 0, 0);
|
||||
@ -91,7 +110,7 @@
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
bottom: -50px;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
overflow: hidden;
|
||||
animation: roadStab 1s ease-out infinite;
|
||||
}
|
||||
@ -103,7 +122,7 @@
|
||||
border-right: 2px solid transparent;
|
||||
border-bottom: 4px solid white;
|
||||
bottom: $bottom;
|
||||
right: -2%;
|
||||
inset-inline-end: -2%;
|
||||
animation: rockTravelling 10s $delay ease-out infinite;
|
||||
}
|
||||
}
|
||||
@ -116,37 +135,37 @@
|
||||
|
||||
@keyframes rockTravelling {
|
||||
0% {
|
||||
right: -2%;
|
||||
inset-inline-end: -2%;
|
||||
}
|
||||
10% {
|
||||
right: 8%;
|
||||
inset-inline-end: 8%;
|
||||
}
|
||||
20% {
|
||||
right: 18%;
|
||||
inset-inline-end: 18%;
|
||||
}
|
||||
30% {
|
||||
right: 29%;
|
||||
inset-inline-end: 29%;
|
||||
}
|
||||
40% {
|
||||
right: 40%;
|
||||
inset-inline-end: 40%;
|
||||
}
|
||||
50% {
|
||||
right: 51%;
|
||||
inset-inline-end: 51%;
|
||||
}
|
||||
60% {
|
||||
right: 62%;
|
||||
inset-inline-end: 62%;
|
||||
}
|
||||
70% {
|
||||
right: 72%;
|
||||
inset-inline-end: 72%;
|
||||
}
|
||||
80% {
|
||||
right: 82%;
|
||||
inset-inline-end: 82%;
|
||||
}
|
||||
90% {
|
||||
right: 92%;
|
||||
inset-inline-end: 92%;
|
||||
}
|
||||
100% {
|
||||
right: 102%;
|
||||
inset-inline-end: 102%;
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,7 +177,7 @@
|
||||
animation: roadStab 1s ease-out infinite, cloudStab 1s ease-out infinite;
|
||||
position: absolute;
|
||||
bottom: -50px;
|
||||
left: -50%;
|
||||
inset-inline-start: -50%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@ -183,7 +202,7 @@
|
||||
composes: cloud;
|
||||
|
||||
top: 65px;
|
||||
right: -30%;
|
||||
inset-inline-end: -30%;
|
||||
width: 50px;
|
||||
height: 16px;
|
||||
animation: cloudTravelling 21s 5s linear infinite;
|
||||
@ -193,7 +212,7 @@
|
||||
composes: cloud;
|
||||
|
||||
top: 40px;
|
||||
right: -30%;
|
||||
inset-inline-end: -30%;
|
||||
width: 70px;
|
||||
height: 22px;
|
||||
animation: cloudTravelling 26s 11s linear infinite;
|
||||
@ -201,10 +220,10 @@
|
||||
|
||||
@keyframes cloudTravelling {
|
||||
0% {
|
||||
right: -30%;
|
||||
inset-inline-end: -30%;
|
||||
}
|
||||
100% {
|
||||
right: 110%;
|
||||
inset-inline-end: 110%;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,12 +34,10 @@ $sidebar-width: 320px;
|
||||
@media (min-width: 720px) {
|
||||
.content {
|
||||
padding: 55px 50px;
|
||||
margin-left: $sidebar-width;
|
||||
margin-inline-start: $sidebar-width;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
right: auto;
|
||||
|
||||
width: $sidebar-width;
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
left: 0;
|
||||
inset-inline-start: 0; // TODO: does nothing. Maybe should be reimplemented?
|
||||
|
||||
text-align: center;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
|
||||
text-align: center;
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Route, Switch } from 'react-router-dom';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
import clsx from 'clsx';
|
||||
|
||||
import { connect } from 'app/functions';
|
||||
@ -54,10 +53,6 @@ class RootPage extends React.PureComponent<{
|
||||
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<Helmet>
|
||||
<html lang={user.lang} />
|
||||
</Helmet>
|
||||
|
||||
<ScrollIntoView top />
|
||||
|
||||
<div
|
||||
|
@ -32,7 +32,7 @@ $toolbarHeight: 50px;
|
||||
|
||||
.toolbarContent {
|
||||
composes: wrapper;
|
||||
position: relative;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.siteName {
|
||||
@ -44,15 +44,11 @@ $toolbarHeight: 50px;
|
||||
|
||||
font-family: $font-family-title;
|
||||
font-size: 33px;
|
||||
color: #fff!important; // TODO: why?
|
||||
color: #fff!important; // Important to remove hover effect, which is inherited from the global <a> style
|
||||
}
|
||||
|
||||
.userBar {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
left: 115px;
|
||||
top: 0;
|
||||
text-align: right;
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
|
||||
.body {
|
||||
|
@ -50,7 +50,7 @@
|
||||
.rulesList {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
padding-left: 20px;
|
||||
padding-inline-start: 20px;
|
||||
}
|
||||
|
||||
.rulesItem {
|
||||
@ -71,7 +71,7 @@
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
left: -40px;
|
||||
inset-inline-start: -40px;
|
||||
width: calc(100% + 60px);
|
||||
height: calc(100% + 20px);
|
||||
background: $white;
|
||||
|
250
packages/app/services/i18n/overrides/intl/udm.js
Normal file
250
packages/app/services/i18n/overrides/intl/udm.js
Normal file
@ -0,0 +1,250 @@
|
||||
IntlPolyfill.__addLocaleData({
|
||||
locale: "udm",
|
||||
date: {
|
||||
ca: ["gregory", "generic"],
|
||||
hourNo0: true,
|
||||
hour12: false,
|
||||
formats: {
|
||||
short: "{1}, {0}",
|
||||
medium: "{1}, {0}",
|
||||
full: "{1}, {0}",
|
||||
long: "{1}, {0}",
|
||||
availableFormats: {
|
||||
d: "d",
|
||||
E: "ccc",
|
||||
Ed: "ccc, d",
|
||||
Ehm: "E h:mm a",
|
||||
EHm: "E HH:mm",
|
||||
Ehms: "E h:mm:ss a",
|
||||
EHms: "E HH:mm:ss",
|
||||
Gy: "G y 'аре'",
|
||||
GyMMM: "LLL G y",
|
||||
GyMMMd: "d MMM G y 'аре'",
|
||||
GyMMMEd: "E, d MMM G y 'аре'",
|
||||
h: "h a",
|
||||
H: "H",
|
||||
hm: "h:mm a",
|
||||
Hm: "H:mm",
|
||||
hms: "h:mm:ss a",
|
||||
Hms: "H:mm:ss",
|
||||
hmsv: "h:mm:ss a v",
|
||||
Hmsv: "H:mm:ss v",
|
||||
hmv: "h:mm a v",
|
||||
Hmv: "H:mm v",
|
||||
M: "L",
|
||||
Md: "dd.MM",
|
||||
MEd: "E, dd.MM",
|
||||
MMdd: "dd.MM",
|
||||
MMM: "LLL",
|
||||
MMMd: "d MMM",
|
||||
MMMEd: "ccc, d MMM",
|
||||
MMMMd: "d MMMM",
|
||||
ms: "mm:ss",
|
||||
y: "y",
|
||||
yM: "MM.y",
|
||||
yMd: "dd.MM.y",
|
||||
yMEd: "ccc, d.MM.y 'аре'",
|
||||
yMM: "MM.y",
|
||||
yMMM: "LLL y 'аре'",
|
||||
yMMMd: "d MMM y 'аре'",
|
||||
yMMMEd: "E, d MMM y 'аре'",
|
||||
yMMMM: "LLLL y 'аре'",
|
||||
yQQQ: "QQQ y 'аре'",
|
||||
yQQQQ: "QQQQ y 'аре'",
|
||||
},
|
||||
dateFormats: {
|
||||
yMMMMEEEEd: "EEEE, d MMMM y 'аре'",
|
||||
yMMMMd: "d MMMM y 'аре'",
|
||||
yMMMd: "d MMM y 'аре'",
|
||||
yMd: "dd.MM.yy",
|
||||
},
|
||||
timeFormats: {
|
||||
hmmsszzzz: "H:mm:ss zzzz",
|
||||
hmsz: "H:mm:ss z",
|
||||
hms: "H:mm:ss",
|
||||
hm: "H:mm",
|
||||
},
|
||||
},
|
||||
calendars: {
|
||||
generic: {
|
||||
months: {
|
||||
narrow: [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
],
|
||||
short: [
|
||||
"Т01",
|
||||
"Т02",
|
||||
"Т03",
|
||||
"Т04",
|
||||
"Т05",
|
||||
"Т06",
|
||||
"Т07",
|
||||
"Т08",
|
||||
"Т09",
|
||||
"Т10",
|
||||
"Т11",
|
||||
"Т12",
|
||||
],
|
||||
long: [
|
||||
"Т01",
|
||||
"Т02",
|
||||
"Т03",
|
||||
"Т04",
|
||||
"Т05",
|
||||
"Т06",
|
||||
"Т07",
|
||||
"Т08",
|
||||
"Т09",
|
||||
"Т10",
|
||||
"Т11",
|
||||
"Т12",
|
||||
],
|
||||
},
|
||||
days: {
|
||||
narrow: ["А", "В", "П", "В", "П", "У", "К"],
|
||||
short: ["ан", "вр", "пк", "вн", "па", "уд", "кн"],
|
||||
long: [
|
||||
"арнянунал",
|
||||
"вордӥськон",
|
||||
"пуксён",
|
||||
"вирнунал",
|
||||
"покчиарня",
|
||||
"удмуртарня",
|
||||
"кӧснунал",
|
||||
],
|
||||
},
|
||||
eras: {
|
||||
narrow: ["ERA0", "ERA1"],
|
||||
short: ["ERA0", "ERA1"],
|
||||
long: ["ERA0", "ERA1"],
|
||||
},
|
||||
dayPeriods: { am: "ЛА", pm: "ЛБ" },
|
||||
},
|
||||
gregory: {
|
||||
months: {
|
||||
narrow: ["Т", "Т", "М", "А", "М", "И", "И", "А", "С", "О", "Н", "Д"],
|
||||
short: [
|
||||
"тшт",
|
||||
"тпт",
|
||||
"южт",
|
||||
"ошт",
|
||||
"крт",
|
||||
"ивт",
|
||||
"пст",
|
||||
"гкт",
|
||||
"кут",
|
||||
"квт",
|
||||
"шкт",
|
||||
"тст",
|
||||
],
|
||||
long: [
|
||||
"толшоре",
|
||||
"тулыспалэ",
|
||||
"южтолэзе",
|
||||
"оштолэзе",
|
||||
"куартолэзе",
|
||||
"инвожое",
|
||||
"пӧсьтолэзе",
|
||||
"гудырикошконэ",
|
||||
"куарусёнэ",
|
||||
"коньывуонэ",
|
||||
"шуркынмонэ",
|
||||
"толсуре",
|
||||
],
|
||||
},
|
||||
days: {
|
||||
narrow: ["А", "В", "П", "В", "П", "У", "К"],
|
||||
short: ["ан", "вр", "пк", "вн", "па", "уд", "кн"],
|
||||
long: [
|
||||
"арнянунал",
|
||||
"вордӥськон",
|
||||
"пуксён",
|
||||
"вирнунал",
|
||||
"покчиарня",
|
||||
"удмуртарня",
|
||||
"кӧснунал",
|
||||
],
|
||||
},
|
||||
eras: {
|
||||
narrow: ["КА", "КБ", "ава", "ав"],
|
||||
short: ["КА", "КБ", "а.в.а", "а.в."],
|
||||
long: [
|
||||
"Кристослэн вордскем азяз",
|
||||
"Кристослэн вордскем бераз",
|
||||
"асьме вакытлэсь азьло",
|
||||
"асьме вакытэ",
|
||||
],
|
||||
},
|
||||
dayPeriods: { am: "ЛА", pm: "ЛБ" },
|
||||
},
|
||||
},
|
||||
},
|
||||
number: {
|
||||
nu: ["latn"],
|
||||
patterns: {
|
||||
decimal: {
|
||||
positivePattern: "{number}",
|
||||
negativePattern: "{minusSign}{number}",
|
||||
},
|
||||
currency: {
|
||||
positivePattern: "{number} {currency}",
|
||||
negativePattern: "{minusSign}{number} {currency}",
|
||||
},
|
||||
percent: {
|
||||
positivePattern: "{number} {percentSign}",
|
||||
negativePattern: "{minusSign}{number} {percentSign}",
|
||||
},
|
||||
},
|
||||
symbols: {
|
||||
latn: {
|
||||
decimal: ",",
|
||||
group: " ",
|
||||
nan: "лыд ӧвӧл",
|
||||
plusSign: "+",
|
||||
minusSign: "-",
|
||||
percentSign: "%",
|
||||
infinity: "∞",
|
||||
},
|
||||
},
|
||||
currencies: {
|
||||
AUD: "A$",
|
||||
BRL: "R$",
|
||||
CAD: "CA$",
|
||||
CNY: "CN¥",
|
||||
EUR: "€",
|
||||
GBP: "£",
|
||||
HKD: "HK$",
|
||||
ILS: "₪",
|
||||
INR: "₹",
|
||||
JPY: "¥",
|
||||
KRW: "₩",
|
||||
MXN: "MX$",
|
||||
NZD: "NZ$",
|
||||
RUB: "₽",
|
||||
RUR: "р.",
|
||||
THB: "฿",
|
||||
TMT: "ТМТ",
|
||||
TWD: "NT$",
|
||||
UAH: "₴",
|
||||
USD: "$",
|
||||
VND: "₫",
|
||||
XAF: "FCFA",
|
||||
XCD: "EC$",
|
||||
XOF: "CFA",
|
||||
XPF: "CFPF",
|
||||
XXX: "XXXX",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
12
packages/app/services/i18n/overrides/pluralrules/udm.js
Normal file
12
packages/app/services/i18n/overrides/pluralrules/udm.js
Normal file
@ -0,0 +1,12 @@
|
||||
Intl.PluralRules && 'function' == typeof Intl.PluralRules.__addLocaleData && Intl.PluralRules.__addLocaleData({
|
||||
data: {
|
||||
udm: {
|
||||
categories: {
|
||||
cardinal: ['other'],
|
||||
ordinal: ['other'],
|
||||
}, fn: function(a, l) {
|
||||
return 'other';
|
||||
},
|
||||
},
|
||||
}, availableLocales: ['udm'], aliases: {}, parentLocales: {},
|
||||
});
|
159
packages/app/services/i18n/overrides/relativetimeformat/udm.js
Normal file
159
packages/app/services/i18n/overrides/relativetimeformat/udm.js
Normal file
@ -0,0 +1,159 @@
|
||||
Intl.RelativeTimeFormat && 'function' == typeof Intl.RelativeTimeFormat.__addLocaleData && Intl.RelativeTimeFormat.__addLocaleData({
|
||||
data: {
|
||||
udm: {
|
||||
nu: ['latn'],
|
||||
year: {
|
||||
0: 'таяз аре',
|
||||
1: 'вуоно аре',
|
||||
'-1': 'кылем аре',
|
||||
past: { other: '{0} ар талэсь азьло' },
|
||||
future: { other: '{0} ар ортчыса' },
|
||||
},
|
||||
'year-short': {
|
||||
0: 'туэ',
|
||||
1: 'вуоно аре',
|
||||
'-1': 'кылем аре',
|
||||
past: { other: '{0} ар талэсь азьло' },
|
||||
future: { other: '{0} ар ортчыса' },
|
||||
},
|
||||
'year-narrow': {
|
||||
0: 'туэ',
|
||||
1: 'кайта',
|
||||
'-1': 'мийым',
|
||||
past: { other: '{0} ар талэсь азьло' },
|
||||
future: { other: '{0} ар ортчыса' },
|
||||
},
|
||||
quarter: {
|
||||
0: 'таяз арньыльмосэ',
|
||||
1: 'вуоно арньыльмосэ',
|
||||
'-1': 'ортчем арньыльмосэ',
|
||||
past: { other: '{0} арньыльмос талэсь азьло' },
|
||||
future: { other: '{0} арныльмос ортчыса' },
|
||||
},
|
||||
'quarter-short': {
|
||||
0: 'таяз арньыльмосэ',
|
||||
1: 'вуоно арньыльмосэ',
|
||||
'-1': 'ортчем арньыльмосэ',
|
||||
past: { other: '{0} арньыльмос талэсь азьло' },
|
||||
future: { other: '{0} арныльмос ортчыса' },
|
||||
},
|
||||
'quarter-narrow': {
|
||||
0: 'таяз арньыльмосэ',
|
||||
1: 'вуоно арньыльмосэ',
|
||||
'-1': 'ортчем арньыльмосэ',
|
||||
past: { other: '{0} арньыльмос талэсь азьло' },
|
||||
future: { other: '{0} арныльмос ортчыса' },
|
||||
},
|
||||
month: {
|
||||
0: 'таяз толэзе',
|
||||
1: 'вуоно толэзе',
|
||||
'-1': 'ортчем толэзе',
|
||||
past: { other: '{0} толэзь талэсь азьло' },
|
||||
future: { other: '{0} толэзь ортчыса' },
|
||||
},
|
||||
'month-short': {
|
||||
0: 'таяз толэзе',
|
||||
1: 'вуоно толэзе',
|
||||
'-1': 'ортчем толэзе',
|
||||
past: { other: '{0} толэзь талэсь азьло' },
|
||||
future: { other: '{0} толэзь ортчыса' },
|
||||
},
|
||||
'month-narrow': {
|
||||
0: 'таяз толэзе',
|
||||
1: 'вуоно толэзе',
|
||||
'-1': 'ортчем толэзе',
|
||||
past: { other: '{0} толэзь талэсь азьло' },
|
||||
future: { other: '{0} толэзь ортчыса' },
|
||||
},
|
||||
week: {
|
||||
0: 'таяз арняе',
|
||||
1: 'вуоно арняе',
|
||||
'-1': 'ортчем арняе',
|
||||
past: { other: '{0} арня талэсь азьло' },
|
||||
future: { other: '{0} арня ортчыса' },
|
||||
},
|
||||
'week-short': {
|
||||
0: 'таяз арняе',
|
||||
1: 'вуоно арняе',
|
||||
'-1': 'ортчем арняе',
|
||||
past: { other: '{0} арня талэсь азьло' },
|
||||
future: { other: '{0} арня ортчыса' },
|
||||
},
|
||||
'week-narrow': {
|
||||
0: 'таяз арняе',
|
||||
1: 'вуоно арняе',
|
||||
'-1': 'ортчем арняе',
|
||||
past: { other: '{0} арня талэсь азьло' },
|
||||
future: { other: '{0} арня ортчыса' },
|
||||
},
|
||||
day: {
|
||||
0: 'туннэ',
|
||||
1: 'ӵуказе',
|
||||
2: 'ӵуказе улыса',
|
||||
'-2': 'валлян',
|
||||
'-1': 'толон',
|
||||
past: { other: '{0} нунал талэсь азьло' },
|
||||
future: { other: '{0} нунал ортчыса' },
|
||||
},
|
||||
'day-short': {
|
||||
0: 'туннэ',
|
||||
1: 'ӵуказе',
|
||||
2: 'ӵуказе улыса',
|
||||
'-2': 'валлян',
|
||||
'-1': 'толон',
|
||||
past: { other: '{0} нунал талэсь азьло' },
|
||||
future: { other: '{0} нунал ортчыса' },
|
||||
},
|
||||
'day-narrow': {
|
||||
0: 'туннэ',
|
||||
1: 'ӵуказе',
|
||||
2: 'усьсэ',
|
||||
'-2': 'валлян',
|
||||
'-1': 'толон',
|
||||
past: { other: '{0} нунал талэсь азьло' },
|
||||
future: { other: '{0} нунал ортчыса' },
|
||||
},
|
||||
hour: { 0: 'таяз часэ', past: { other: '{0} час талэсь азьло' }, future: { other: '{0} час ортчыса' } },
|
||||
'hour-short': {
|
||||
0: 'таяз часэ',
|
||||
past: { other: '{0} час талэсь азьло' },
|
||||
future: { other: '{0} час ортчыса' },
|
||||
},
|
||||
'hour-narrow': {
|
||||
0: 'таяз часэ',
|
||||
past: { other: '{0} час талэсь азьло' },
|
||||
future: { other: '{0} час ортчыса' },
|
||||
},
|
||||
minute: {
|
||||
0: 'таяз минутэ',
|
||||
past: { other: '{0} минут талэсь азьло' },
|
||||
future: { other: '{0} минут ортчыса' },
|
||||
},
|
||||
'minute-short': {
|
||||
0: 'таяз минутэ',
|
||||
past: { other: '{0} минут талэсь азьло' },
|
||||
future: { other: '{0} минут ортчыса' },
|
||||
},
|
||||
'minute-narrow': {
|
||||
0: 'таяз минутэ',
|
||||
past: { other: '{0} минут талэсь азьло' },
|
||||
future: { other: '{0} минут ортчыса' },
|
||||
},
|
||||
second: {
|
||||
0: 'таяз секундэ',
|
||||
past: { other: '{0} секунд талэзь азьло' },
|
||||
future: { other: '{0} секунд ортчыса' },
|
||||
},
|
||||
'second-short': {
|
||||
0: 'таяз секундэ',
|
||||
past: { other: '{0} секунд талэзь азьло' },
|
||||
future: { other: '{0} секунд ортчыса' },
|
||||
},
|
||||
'second-narrow': {
|
||||
0: 'таяз секундэ',
|
||||
past: { other: '{0} секунд талэзь азьло' },
|
||||
future: { other: '{0} секунд ортчыса' },
|
||||
},
|
||||
},
|
||||
}, availableLocales: ['udm'], aliases: {}, parentLocales: {},
|
||||
});
|
@ -28,7 +28,7 @@ const CROWDIN_FILE_PATH = config.filePath;
|
||||
const SOURCE_LANG = config.sourceLang;
|
||||
const LANG_DIR = config.basePath;
|
||||
const INDEX_FILE_NAME = 'index.js';
|
||||
const MIN_RELEASE_PROGRESS = config.minApproved;
|
||||
const MIN_RELEASE_PROGRESS = config.minTranslated;
|
||||
|
||||
const crowdin = new Crowdin({
|
||||
token: config.apiKey,
|
||||
@ -43,6 +43,7 @@ const releasedLocales: ReadonlyArray<string> = ['be', 'fr', 'id', 'pt', 'ru', 'u
|
||||
* Map Crowdin locales into our internal locales representation
|
||||
*/
|
||||
const LOCALES_MAP: Record<string, string> = {
|
||||
'es-ES': 'es',
|
||||
'pt-BR': 'pt',
|
||||
'zh-CN': 'zh',
|
||||
};
|
||||
@ -54,6 +55,7 @@ const LOCALES_MAP: Record<string, string> = {
|
||||
const NATIVE_NAMES_MAP: Record<string, string> = {
|
||||
be: 'Беларуская',
|
||||
cs: 'Čeština',
|
||||
fil: 'Wikang Filipino',
|
||||
id: 'Bahasa Indonesia',
|
||||
lt: 'Lietuvių',
|
||||
pl: 'Polski',
|
||||
@ -67,6 +69,7 @@ const NATIVE_NAMES_MAP: Record<string, string> = {
|
||||
* This arrays allows us to override Crowdin English languages names
|
||||
*/
|
||||
const ENGLISH_NAMES_MAP: Record<string, string> = {
|
||||
fil: 'Filipino',
|
||||
pt: 'Portuguese, Brazilian',
|
||||
sr: 'Serbian',
|
||||
zh: 'Simplified Chinese',
|
||||
@ -225,7 +228,7 @@ async function pull(): Promise<void> {
|
||||
}
|
||||
|
||||
console.log('Pulling translation progress...');
|
||||
const { data: translationProgress } = await crowdin.translationStatusApi.getFileProgress(PROJECT_ID, fileId, 100);
|
||||
const { data: fileProgress } = await crowdin.translationStatusApi.getFileProgress(PROJECT_ID, fileId, 100);
|
||||
|
||||
const localesToPull: Array<string> = [];
|
||||
const indexFileEntries: Record<string, IndexFileEntry> = {
|
||||
@ -238,16 +241,16 @@ async function pull(): Promise<void> {
|
||||
},
|
||||
};
|
||||
|
||||
translationProgress.forEach(({ data: { languageId, approvalProgress } }) => {
|
||||
fileProgress.forEach(({ data: { languageId, translationProgress } }) => {
|
||||
const locale = toInternalLocale(languageId);
|
||||
|
||||
if (releasedLocales.includes(locale) || approvalProgress >= MIN_RELEASE_PROGRESS) {
|
||||
if (releasedLocales.includes(locale) || translationProgress >= MIN_RELEASE_PROGRESS) {
|
||||
localesToPull.push(languageId);
|
||||
indexFileEntries[locale] = {
|
||||
code: locale,
|
||||
name: NATIVE_NAMES_MAP[locale] || iso639.getNativeName(locale),
|
||||
englishName: ENGLISH_NAMES_MAP[locale] || iso639.getName(locale),
|
||||
progress: approvalProgress,
|
||||
progress: translationProgress,
|
||||
isReleased: releasedLocales.includes(locale),
|
||||
};
|
||||
}
|
||||
@ -268,7 +271,6 @@ async function pull(): Promise<void> {
|
||||
data: { url },
|
||||
} = await crowdin.translationsApi.buildProjectFileTranslation(PROJECT_ID, fileId, {
|
||||
targetLanguageId: languageId,
|
||||
exportApprovedOnly: true,
|
||||
});
|
||||
|
||||
const { data: fileContents } = await axios.get(url, {
|
||||
|
@ -47,6 +47,7 @@ module.exports = ({ webpack: loader }) => ({
|
||||
return defaultLoad(filename, importOptions);
|
||||
})(require('postcss-import/lib/load-content')),
|
||||
},
|
||||
'postcss-bidirection': {},
|
||||
// TODO: for some reason cssnano strips out @mixin declarations
|
||||
// cssnano: {
|
||||
// /**
|
||||
|
19
postinstall.js
Executable file
19
postinstall.js
Executable file
@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const localeOverrides = {
|
||||
'packages/app/services/i18n/overrides/intl': 'node_modules/intl/locale-data/jsonp',
|
||||
'packages/app/services/i18n/overrides/pluralrules': 'node_modules/@formatjs/intl-pluralrules/dist/locale-data',
|
||||
// eslint-disable-next-line prettier/prettier
|
||||
'packages/app/services/i18n/overrides/relativetimeformat': 'node_modules/@formatjs/intl-relativetimeformat/dist/locale-data',
|
||||
};
|
||||
|
||||
Object.entries(localeOverrides).forEach(([sourceDir, targetDir]) => {
|
||||
fs.readdirSync(sourceDir).forEach((localeFile) => {
|
||||
fs.copyFileSync(path.join(sourceDir, localeFile), path.join(targetDir, localeFile));
|
||||
});
|
||||
});
|
@ -201,19 +201,6 @@ const webpackConfig = {
|
||||
type: 'javascript/auto',
|
||||
use: ['fontgen-loader'],
|
||||
},
|
||||
{
|
||||
// Replace some locales provided by FormatJS with local ones
|
||||
test: /@formatjs\/intl-\w+\/dist\/locale-data/,
|
||||
loader: 'file-replace-loader',
|
||||
options: {
|
||||
condition: 'if-replacement-exists',
|
||||
replacement: (resource) =>
|
||||
resource.replace(
|
||||
/node_modules\/@formatjs\/intl-(\w+)\/dist\/locale-data\/(\w+)\.js/,
|
||||
'packages/app/services/i18n/overrides/$1/$2.js',
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
|
25
yarn.lock
25
yarn.lock
@ -3439,6 +3439,11 @@
|
||||
"@types/prop-types" "*"
|
||||
csstype "^3.0.2"
|
||||
|
||||
"@types/rtl-detect@^1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/rtl-detect/-/rtl-detect-1.0.0.tgz#5791e18a111f2b8b5b328160af97f3991a5697a5"
|
||||
integrity sha512-lyYh44YgrejEK9/5rhASghvRUOxrSJyyyQmqK7L6F/V5qs6PY1RfCi1VbjSkY6kuDt7lzQyhd006slhda4Oypg==
|
||||
|
||||
"@types/sax@^1.2.1":
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/sax/-/sax-1.2.1.tgz#e0248be936ece791a82db1a57f3fb5f7c87e8172"
|
||||
@ -12535,6 +12540,12 @@ posix-character-classes@^0.1.0:
|
||||
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
|
||||
integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
|
||||
|
||||
"postcss-bidirection@https://github.com/erickskrauch/postcss-bidirection.git#iss_23":
|
||||
version "2.7.2"
|
||||
resolved "https://github.com/erickskrauch/postcss-bidirection.git#feabf42c8ab5cf6b0e22f78de04984e22cf42ba4"
|
||||
dependencies:
|
||||
postcss "^7.0.13"
|
||||
|
||||
postcss-calc@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436"
|
||||
@ -12917,6 +12928,15 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.2
|
||||
source-map "^0.6.1"
|
||||
supports-color "^6.1.0"
|
||||
|
||||
postcss@^7.0.13:
|
||||
version "7.0.35"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24"
|
||||
integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==
|
||||
dependencies:
|
||||
chalk "^2.4.2"
|
||||
source-map "^0.6.1"
|
||||
supports-color "^6.1.0"
|
||||
|
||||
postcss@^7.0.26:
|
||||
version "7.0.26"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.26.tgz#5ed615cfcab35ba9bbb82414a4fa88ea10429587"
|
||||
@ -14246,6 +14266,11 @@ rsvp@^4.8.4:
|
||||
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734"
|
||||
integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==
|
||||
|
||||
rtl-detect@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/rtl-detect/-/rtl-detect-1.0.2.tgz#8eca316f5c6563d54df4e406171dd7819adda67f"
|
||||
integrity sha512-5X1422hvphzg2a/bo4tIDbjFjbJUOaPZwqE6dnyyxqwFqfR+tBcvfqapJr0o0VygATVCGKiODEewhZtKF+90AA==
|
||||
|
||||
run-async@^2.2.0, run-async@^2.4.0:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
|
||||
|
Loading…
Reference in New Issue
Block a user