Merge pull request #1 from regru/85773_do-nginx-config-generator_reuse

85773 reusing Digital Ocean NGINX-config-generator
This commit is contained in:
Valery Kovalev 2021-05-04 18:08:06 +03:00 committed by GitHub
commit b7075be560
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 255 additions and 74 deletions

1
.gitignore vendored
View File

@ -5,5 +5,4 @@ node_modules
.DS_Store
/build/
/dist/
/dev/

9
build/base.html Normal file
View File

@ -0,0 +1,9 @@
<!DOCTYPE html><html lang="en"><!-- Last fetch from www.digitalocean.com @ 2021-04-23T15:11:24.821Z -->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
</head>
<body>
<block name="title"><title>DigitalOcean</title></block>
<div class="wrapper layout-wrapper"><block name="content"></block>
</body></html>

9
build/index.html Normal file
View File

@ -0,0 +1,9 @@
<!DOCTYPE html><html lang="en"><!-- Last fetch from www.digitalocean.com @ 2021-04-23T15:11:24.821Z -->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
</head>
<body>
<title>NGINXConfig | REG.RU</title>
<div class="wrapper layout-wrapper"><div id="app"></div>
</body></html>

1
build/prism.css Normal file

File diff suppressed because one or more lines are too long

1
dist/css/app.css vendored Normal file

File diff suppressed because one or more lines are too long

BIN
dist/fonts/Inter-Bold.ttf vendored Normal file

Binary file not shown.

BIN
dist/fonts/Inter-Bold.woff vendored Normal file

Binary file not shown.

BIN
dist/fonts/Inter-Bold.woff2 vendored Normal file

Binary file not shown.

BIN
dist/fonts/Inter-Light.ttf vendored Normal file

Binary file not shown.

BIN
dist/fonts/Inter-Light.woff vendored Normal file

Binary file not shown.

BIN
dist/fonts/Inter-Light.woff2 vendored Normal file

Binary file not shown.

BIN
dist/fonts/Inter-Medium.ttf vendored Normal file

Binary file not shown.

BIN
dist/fonts/Inter-Medium.woff vendored Normal file

Binary file not shown.

BIN
dist/fonts/Inter-Medium.woff2 vendored Normal file

Binary file not shown.

BIN
dist/fonts/Inter-Regular.ttf vendored Normal file

Binary file not shown.

BIN
dist/fonts/Inter-Regular.woff vendored Normal file

Binary file not shown.

BIN
dist/fonts/Inter-Regular.woff2 vendored Normal file

Binary file not shown.

1
dist/index.html vendored Normal file
View File

@ -0,0 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><script defer="defer" src="js/chunk-vendors.js"></script><script defer="defer" src="js/app.js"></script><link href="css/app.css" rel="stylesheet"></head><body><title>NGINXConfig | REG.RU</title><div class="wrapper layout-wrapper"><div id="app"></div></div></body></html>

1
dist/js/10.js vendored Normal file
View File

@ -0,0 +1 @@
(self["webpackChunknginxconfig_io"]=self["webpackChunknginxconfig_io"]||[]).push([[10],{2010:(e,n,i)=>{"use strict";i.r(n),i.d(n,{default:()=>c});var o=function(){var e=this,n=e.$createElement,i=e._self._c||n;return i("div",{class:"column "+(e.half?"is-half":"is-full")+" is-full-mobile is-full-tablet",on:{copied:e.copied}},[i("h3",{domProps:{innerHTML:e._s(e.name)}}),i("pre",[i("code",{staticClass:"language-docker",domProps:{innerHTML:e._s(e.conf)}})])])},s=[];i(7158);const l={name:"DockerPrism",props:{name:String,conf:String,half:Boolean},mounted(){console.info(`Highlighting ${this.$props.name}...`),window.Prism.highlightAllUnder(this.$el)},methods:{copied(e){this.$emit("copied",e.detail.text)}}},r=l;var t=i(5961),a=(0,t.Z)(r,o,s,!1,null,null,null);const c=a.exports},7158:()=>{Prism.languages.docker={keyword:{pattern:/(^\s*)(?:ADD|ARG|CMD|COPY|ENTRYPOINT|ENV|EXPOSE|FROM|HEALTHCHECK|LABEL|MAINTAINER|ONBUILD|RUN|SHELL|STOPSIGNAL|USER|VOLUME|WORKDIR)(?=\s)/im,lookbehind:!0},string:/("|')(?:(?!\1)[^\\\r\n]|\\(?:\r\n|[\s\S]))*\1/,comment:{pattern:/#.*/,greedy:!0},punctuation:/---|\.\.\.|[:[\]{}\-,|>?]/},Prism.languages.dockerfile=Prism.languages.docker}}]);

1
dist/js/136.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/js/172.js vendored Normal file
View File

@ -0,0 +1 @@
(self["webpackChunknginxconfig_io"]=self["webpackChunknginxconfig_io"]||[]).push([[172],{9172:(e,n,r)=>{"use strict";r.r(n),r.d(n,{default:()=>u});var t=function(){var e=this,n=e.$createElement,r=e._self._c||n;return r("div",{class:"column "+(e.half?"is-half":"is-full")+" is-full-mobile is-full-tablet",on:{copied:e.copied}},[r("h3",{domProps:{innerHTML:e._s(e.name)}}),r("pre",[r("code",{staticClass:"language-yaml",domProps:{innerHTML:e._s(e.conf)}})])])},o=[];r(3358);const a={name:"YamlPrism",props:{name:String,conf:String,half:Boolean},mounted(){console.info(`Highlighting ${this.$props.name}...`),window.Prism.highlightAllUnder(this.$el)},methods:{copied(e){this.$emit("copied",e.detail.text)}}},i=a;var l=r(5961),s=(0,l.Z)(i,t,o,!1,null,null,null);const u=s.exports},3358:()=>{(function(e){var n=/[*&][^\s[\]{},]+/,r=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,t="(?:"+r.source+"(?:[ \t]+"+n.source+")?|"+n.source+"(?:[ \t]+"+r.source+")?)",o=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-]<PLAIN>)(?:[ \t]*(?:(?![#:])<PLAIN>|:<PLAIN>))*/.source.replace(/<PLAIN>/g,(function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source})),a=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function i(e,n){n=(n||"").replace(/m/g,"")+"m";var r=/([:\-,[{]\s*(?:\s<<prop>>[ \t]+)?)(?:<<value>>)(?=[ \t]*(?:$|,|]|}|(?:[\r\n]\s*)?#))/.source.replace(/<<prop>>/g,(function(){return t})).replace(/<<value>>/g,(function(){return e}));return RegExp(r,n)}e.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s<<prop>>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/<<prop>>/g,(function(){return t}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:<<prop>>[ \t]+)?)<<key>>(?=\s*:\s)/.source.replace(/<<prop>>/g,(function(){return t})).replace(/<<key>>/g,(function(){return"(?:"+o+"|"+a+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:i(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:i(/true|false/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:i(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:i(a),lookbehind:!0,greedy:!0},number:{pattern:i(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.?\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:r,important:n,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml})(Prism)}}]);

1
dist/js/2.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/js/481.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/js/763.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/js/859.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/js/app.js vendored Normal file

File diff suppressed because one or more lines are too long

85
dist/js/chunk-vendors.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -10,8 +10,9 @@
"main": "src/nginxconfig/mount.js",
"scripts": {
"build": "npm run build:clean && npm run build:template && npm run build:prism && npm run build:static && npm run build:tool",
"build:regru-static": "npm run build:clean && npm run build:template && npm run build:tool",
"build:clean": "do-vue clean",
"build:template": "do-vue template && node src/nginxconfig/build/template.js",
"build:template": "node src/nginxconfig/build/template.js",
"build:prism": "node src/nginxconfig/build/prism.js",
"build:static": "copyfiles --up 2 src/static/{*,**/*} dist",
"build:tool": "vue-cli-service build src/nginxconfig/mount.js --no-clean",

View File

@ -33,7 +33,7 @@ const main = () => {
let template = fs.readFileSync(path.join(buildDir, 'base.html'), 'utf8');
// Inject our title now
template = template.replace('<block name="title"><title>DigitalOcean</title></block>', '<title>NGINXConfig | DigitalOcean</title>');
template = template.replace('<block name="title"><title>DigitalOcean</title></block>', '<title>NGINXConfig | REG.RU</title>');
// We don't need the head/script blocks, vue-cli-service handles those
template = template.replace('<block name="head"></block>', '');

View File

@ -27,4 +27,6 @@ THE SOFTWARE.
export default {
downloadConfig: 'Download Config',
copyBase64: 'Copy Base64',
copied: 'Copied',
press_to_copy: 'Press Ctrl+C to copy',
};

View File

@ -40,6 +40,7 @@ export default {
magento: 'Magento',
joomla: 'Joomla',
django: 'Django',
nodejs: 'Node.js',
logging: 'Логирование',
reverseProxy: 'Обратный прокси',
reverseProxyLower: 'обратный прокси',

View File

@ -27,8 +27,8 @@ THE SOFTWARE.
import common from '../common';
export default {
title: `${common.nginx}Config`,
description: `Самый простой способ настроить производительный, безопасный и стабильный ${common.nginx} сервер.`,
title: `Сервис настройки ${common.nginx}`,
description: `Заполните форму и сервис подготовит конфигурационные файлы веб-сервера ${common.nginx} для вашего кейса веб-сервер, сервер для ${common.django} или ${common.nodejs}, сервер для CMS ${common.wordPress}, ${common.joomla}, ${common.drupal}. Настройка возможна как для одного и нескольких доменов. Готовые файлы конфигурации можно скачать или выполнить одну команду на сервере для автоматического обновления.`,
singleColumnMode: 'Одноколоночный режим',
splitColumnMode: 'Режим разделения столбца',
perWebsiteConfig: 'Конфигурация для каждого сайта',

View File

@ -27,4 +27,6 @@ THE SOFTWARE.
export default {
downloadConfig: 'Скачать конфигурацию',
copyBase64: 'Копировать Base64',
copied: 'Скопировано',
press_to_copy: 'Нажмите Ctrl+C чтобы скопировать',
};

View File

@ -54,6 +54,11 @@ pre {
text-align: initial;
vertical-align: initial;
}
&.function,
&.keyword {
color: $header;
}
}
}
}

View File

@ -25,10 +25,10 @@ THE SOFTWARE.
*/
.header {
padding: ($margin * 2) $margin ($margin * 1.5);
padding: ($margin) ($margin * 0.5) 0;
@media (min-width: $breakpoint) {
padding: ($margin * 3.75) 0 ($margin * .5);
padding: ($margin) 0 0;
}
.container {
@ -36,6 +36,11 @@ THE SOFTWARE.
@include font-medium;
}
p {
font-size: medium;
color: #364364;
}
form {
.input-container {
margin: 0;

View File

@ -38,7 +38,6 @@ THE SOFTWARE.
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
}
.header-group {
@ -48,6 +47,7 @@ THE SOFTWARE.
.button {
&.is-tiny {
background-color: lightgray;
font-size: 20px;
}
}
@ -59,10 +59,14 @@ THE SOFTWARE.
}
.buttons-group {
align-items: center;
.button {
margin: 0 .25rem .5rem;
flex: 1 1 auto;
&.is-primary {
background-color: $header;
color: $callout;
}
}
}
}
@ -87,6 +91,8 @@ THE SOFTWARE.
.button {
margin-left: .5rem;
color: $callout;
background-color: $header;
i + span,
span + i {
@ -94,4 +100,8 @@ THE SOFTWARE.
}
}
}
.dark-button {
background-color: $header;
}
}

View File

@ -31,6 +31,7 @@ THE SOFTWARE.
overflow-wrap: break-word;
a {
color: $header;
text-decoration: none;
}
}
@ -47,4 +48,8 @@ THE SOFTWARE.
.buttons {
margin: 1rem 0;
}
.dark-button {
background-color: $header;
}
}

View File

@ -35,25 +35,24 @@ THE SOFTWARE.
&:focus {
a {
&::after {
background: $dark-blue;
background: $header;
}
}
}
// Light blue color if the user has gone past a tab
&.is-before {
a {
color: mix($dark-grey, $primary);
color: mix($header, $header);
&::after {
background: rgba($primary, .5);
background: rgba($header, .5);
}
&:hover {
color: $dark-blue;
color: $header;
&::after {
background: $dark-blue;
background: $header;
}
}
}
@ -62,7 +61,7 @@ THE SOFTWARE.
// If a user has changed something in the tab, we'll make the text dark always
&.is-changed {
a {
color: $dark-blue;
color: $header;
}
}

View File

@ -24,7 +24,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
$header: #0071fe;
$header: #066BC6;
$highlight: #f2c94c;
$callout: #f3f5f9;
@import "~do-bulma/src/style";
@ -32,14 +32,14 @@ $callout: #f3f5f9;
.do-bulma {
@import "../../../build/prism";
$pretty--color-dark: $primary;
$pretty--color-default: $primary;
$pretty--color-dark: $header;
$pretty--color-default: $header;
@import "~pretty-checkbox/src/pretty-checkbox";
$vs-border-color: $border;
$vs-border-radius: $border-radius;
$vs-dropdown-box-shadow: 0 2px 4px rgba($dark-blue, .06);
$vs-state-active-bg: $primary;
$vs-dropdown-box-shadow: 0 2px 4px rgba($header, .06);
$vs-state-active-bg: $header;
@import "~vue-select/src/scss/vue-select";
@import "header";

View File

@ -27,12 +27,10 @@ THE SOFTWARE.
<template>
<div class="all do-bulma">
<Header :title="$t('templates.app.title')">
<template #description>
{{ $t('templates.app.description') }}
</template>
<template #header>
<p>{{ $t('templates.app.description') }}</p>
</template>
<template #buttons>
<!-- <template #buttons>
<VueSelect v-model="lang"
:options="i18nPacks"
:clearable="false"
@ -53,7 +51,7 @@ THE SOFTWARE.
<a v-else class="button is-primary is-hidden-touch" @click="splitColumnToggle">
{{ $t('templates.app.splitColumnMode') }}
</a>
</template>
</template> -->
</Header>
<div class="main container" :style="{ display: ready ? undefined : 'none' }">
@ -63,7 +61,10 @@ THE SOFTWARE.
<div class="tabs">
<ul>
<li v-for="data in activeDomains" :class="data[1] === active ? 'is-active' : undefined">
<li v-for="data in activeDomains"
:key="data[0].server.domain.computed"
:class="data[1] === active ? 'is-active' : undefined"
>
<a class="domain" @click="active = data[1]">
{{ data[0].server.domain.computed }}{{ changes(data[1]) }}
</a>
@ -87,7 +88,7 @@ THE SOFTWARE.
<h2>{{ $t('templates.app.globalConfig') }}</h2>
<Global :data="global"></Global>
<DropletCallout></DropletCallout>
<!-- <DropletCallout></DropletCallout> -->
<h2>{{ $t('templates.app.setup') }}</h2>
<Setup :data="{ domains: domains.filter(d => d !== null), global, confFiles }"></Setup>
@ -110,9 +111,6 @@ THE SOFTWARE.
</div>
</div>
</div>
<Footer></Footer>
<ContributeCallout></ContributeCallout>
</div>
</template>
@ -262,10 +260,10 @@ THE SOFTWARE.
const imported = await importData(query, this.$data.domains, this.$data.global, this.$nextTick);
// Apply browser language if not specified in query
if (!imported || !imported.global || !imported.global.app || !imported.global.app.lang) {
const language = browserLanguage(availablePacks);
if (language) this.lang = language;
}
// if (!imported || !imported.global || !imported.global.app || !imported.global.app.lang) {
// const language = browserLanguage(availablePacks);
// if (language) this.lang = language;
// }
// Initial analytics events
this.splitColumnEvent(true);

View File

@ -33,7 +33,10 @@ THE SOFTWARE.
<div class="panel">
<div class="tabs">
<ul>
<li v-for="tab in tabs" :class="tabClass(tab.key)">
<li v-for="tab in tabs"
:key="tab.key"
:class="tabClass(tab.key)"
>
<a @click="showTab(tab.key)">{{ $t(tab.display) }}{{ changes(tab.key) }}</a>
</li>
</ul>
@ -63,9 +66,9 @@ THE SOFTWARE.
import analytics from '../util/analytics';
import isChanged from '../util/is_changed';
import Presets from './domain_sections/presets';
import * as Sections from './domain_sections';
import Sections from './domain_sections';
const tabs = Object.values(Sections);
const tabs = Sections;
const delegated = {
hasUserInteraction: false,
presets: Presets.delegated,

View File

@ -24,12 +24,24 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
export { default as Server } from './server';
export { default as HTTPS } from './https';
export { default as PHP } from './php';
export { default as Python } from './python';
export { default as ReverseProxy } from './reverse_proxy';
export { default as Routing } from './routing';
export { default as Logging } from './logging';
export { default as Restrict } from './restrict';
export { default as Onion } from './onion';
import Server from './server';
import HTTPS from './https';
import PHP from './php';
import Python from './python';
import ReverseProxy from './reverse_proxy';
import Routing from './routing';
import Logging from './logging';
import Restrict from './restrict';
import Onion from './onion';
export default [
Server,
HTTPS,
PHP,
Python,
ReverseProxy,
Routing,
Logging,
Restrict,
Onion,
];

View File

@ -28,7 +28,10 @@ THE SOFTWARE.
<div class="panel">
<div class="tabs">
<ul>
<li v-for="tab in tabs" :class="tabClass(tab.key)">
<li v-for="tab in tabs"
:key="tab.key"
:class="tabClass(tab.key)"
>
<a @click="showTab(tab.key)">{{ $t(tab.display) }}{{ changes(tab.key) }}</a>
</li>
</ul>
@ -56,9 +59,9 @@ THE SOFTWARE.
<script>
import analytics from '../util/analytics';
import isChanged from '../util/is_changed';
import * as Sections from './global_sections';
import Sections from './global_sections';
const tabs = Object.values(Sections);
const tabs = Sections;
const delegated = tabs.reduce((prev, tab) => {
prev[tab.key] = tab.delegated;
return prev;

View File

@ -32,7 +32,7 @@ THE SOFTWARE.
</div>
<div class="field-body">
<div class="field is-horizontal is-aligned-top">
<a class="button is-primary is-tiny" @click="applyDockerTweaks">
<a class="button is-primary is-tiny dark-button" @click="applyDockerTweaks">
{{ $t('templates.globalSections.docker.applyDockerTweaks') }}
</a>
<p>

View File

@ -24,12 +24,24 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
export { default as HTTPS } from './https';
export { default as Security } from './security';
export { default as Python } from './python';
export { default as ReverseProxy } from './reverse_proxy';
export { default as Performance } from './performance';
export { default as Logging } from './logging';
export { default as NGINX } from './nginx';
export { default as Docker } from './docker';
export { default as Tools } from './tools';
import HTTPS from './https';
import Security from './security';
import Python from './python';
import ReverseProxy from './reverse_proxy';
import Performance from './performance';
import Logging from './logging';
import NGINX from './nginx';
import Docker from './docker';
import Tools from './tools';
export default [
HTTPS,
Security,
Python,
ReverseProxy,
Performance,
Logging,
NGINX,
Docker,
Tools,
];

View File

@ -29,7 +29,10 @@ THE SOFTWARE.
<div class="panel">
<div class="tabs">
<ul>
<li v-for="tab in tabs" :class="tabClass(tab.key)">
<li v-for="tab in tabs"
:key="tab.key"
:class="tabClass(tab.key)"
>
<a @click="showTab(tab.key)">{{ $t(tab.display) }}</a>
</li>
</ul>
@ -55,7 +58,7 @@ THE SOFTWARE.
<div class="buttons is-centered">
<a class="button is-success" @click="downloadTar">{{ $t('templates.setup.downloadConfig') }}</a>
<a ref="copyTar" class="button is-primary">{{ $t('templates.setup.copyBase64') }}</a>
<a ref="copyTar" class="button is-primary dark-button">{{ $t('templates.setup.copyBase64') }}</a>
</div>
</div>
</template>
@ -64,9 +67,9 @@ THE SOFTWARE.
import Tar from 'memory-tar-create';
import ClipboardJS from 'clipboard';
import analytics from '../util/analytics';
import * as Sections from './setup_sections';
import Sections from './setup_sections';
const tabs = Object.values(Sections);
const tabs = Sections;
export default {
name: 'Setup',
@ -164,13 +167,13 @@ THE SOFTWARE.
});
clipboard.on('success', e => {
elm.textContent = 'Copied';
elm.textContent = this.$t('templates.setup.copied');
e.clearSelection();
resetText();
});
clipboard.on('error', () => {
elm.textContent = 'Press Ctrl + C to copy';
elm.textContent = this.$t('templates.setup.press_to_copy');
resetText();
});
},

View File

@ -24,7 +24,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
export { default as Download } from './download';
export { default as SSL } from './ssl';
export { default as Certbot } from './certbot';
export { default as GoLive } from './go_live';
import Download from './download';
import SSL from './ssl';
import Certbot from './certbot';
import GoLive from './go_live';
export default [
Download,
SSL,
Certbot,
GoLive,
];

View File

@ -25,6 +25,6 @@ THE SOFTWARE.
*/
export const defaultPack = 'en';
export const defaultPack = 'ru';
export { default as defaultPackData } from '../i18n/en';
export { default as defaultPackData } from '../i18n/ru';