impr: ⚡ Migliorata i18n
Spostata funzione di traduzione JS all'interno di `utils.js` e poi portata in una variabile globale. Le traduzioni sono ora salvate nella cache.
This commit is contained in:
parent
2e18a96e5e
commit
0fd3c9a313
|
@ -1,3 +1,5 @@
|
|||
root: true
|
||||
extends:
|
||||
- '@openstamanager'
|
||||
globals:
|
||||
__: true
|
||||
|
|
|
@ -4,7 +4,6 @@ namespace App\Http\Middleware;
|
|||
|
||||
use Illuminate\Http\Request;
|
||||
use Inertia\Middleware;
|
||||
use Nette\Utils\Json;
|
||||
|
||||
class HandleInertiaRequests extends Middleware
|
||||
{
|
||||
|
@ -17,41 +16,24 @@ class HandleInertiaRequests extends Middleware
|
|||
*/
|
||||
protected $rootView = 'app';
|
||||
|
||||
/**
|
||||
* Determines the current asset version.
|
||||
*
|
||||
* @see https://inertiajs.com/asset-versioning
|
||||
*/
|
||||
public function version(Request $request): string|null
|
||||
{
|
||||
return parent::version($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the props that are shared by default.
|
||||
*
|
||||
* @see https://inertiajs.com/shared-data
|
||||
*/
|
||||
public function share(Request $request): array
|
||||
final public function share(Request $request): array
|
||||
{
|
||||
return array_merge(parent::share($request), [
|
||||
'locale' => fn () => app()->getLocale(),
|
||||
'translations' => function () {
|
||||
$json = resource_path('lang/'.app()->getLocale().'.json');
|
||||
if (!is_file($json)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Json::decode(file_get_contents($json));
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
public function rootView(Request $request): string
|
||||
final public function rootView(Request $request): string
|
||||
{
|
||||
if (in_array($request->route()?->uri(), ['setup', 'login'], true)) {
|
||||
return 'external';
|
||||
}
|
||||
|
||||
return $this->rootView;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Nette\Utils\Json;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
@ -19,6 +20,11 @@ class AppServiceProvider extends ServiceProvider
|
|||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
//
|
||||
cache()->rememberForever(
|
||||
'translations_' . app()->getLocale(),
|
||||
fn () => Json::encode(
|
||||
Json::decode(file_get_contents(resource_path('lang/'.app()->getLocale().'.json')))
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
import {Vnode} from 'mithril';
|
||||
import {sync as render} from 'mithril-node-render';
|
||||
|
||||
import {containsHTML} from '../utils';
|
||||
import Component from './Component.jsx';
|
||||
|
||||
/**
|
||||
|
@ -14,48 +10,8 @@ export default class Page extends Component {
|
|||
component: string,
|
||||
locale: string,
|
||||
props: {...},
|
||||
translations: {...},
|
||||
url: string,
|
||||
version: string,
|
||||
...
|
||||
} = JSON.parse($('#app').attr('data-page'));
|
||||
|
||||
/**
|
||||
* Ritorna una traduzione
|
||||
*
|
||||
* @param {string|Vnode} key Stringa di cui prelevare la traduzione
|
||||
* @param {Object|boolean} replace Eventuali parametri da rimpiazzare.
|
||||
* Se il parametro è "true" (valore booleano), verrà ritornato il valore come stringa
|
||||
* (stesso funzionamento del parametro dedicato (sotto ↓))
|
||||
* @param {boolean} returnAsString Se impostato a "true" vien ritornata una stringa invece di
|
||||
* un Vnode di Mithril
|
||||
*
|
||||
* @returns {Vnode}
|
||||
*
|
||||
* @protected
|
||||
*/
|
||||
__(
|
||||
key: string | Vnode,
|
||||
replace: {...} | boolean = {},
|
||||
returnAsString: boolean = false
|
||||
): Vnode {
|
||||
let translation = (this.page.translations && this.page.translations[key])
|
||||
? this.page.translations[key] : key;
|
||||
|
||||
// Ritorna la traduzione come stringa (senza sostituzione di parametri)
|
||||
if ((typeof replace === 'boolean' && replace) || (replace.length === 0 && !containsHTML(translation))) {
|
||||
return translation;
|
||||
}
|
||||
|
||||
for (const k of Object.keys(replace)) {
|
||||
// `'attrs' in replace[k]` controlla se replace[k] è un vnode di Mithril
|
||||
translation = translation.replace(`:${k}`, ((typeof replace[k] === 'object' && 'attrs' in replace[k]) ? render(replace[k]) : replace[k]));
|
||||
}
|
||||
|
||||
if (returnAsString || !containsHTML(translation)) {
|
||||
return translation;
|
||||
}
|
||||
|
||||
return window.m.trust(translation);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -145,7 +145,7 @@ export default class RecordsPage extends Page {
|
|||
<TableRow>
|
||||
<TableCell colspan={collect(this.columns)
|
||||
.count()} style="text-align: center;">
|
||||
{this.__('Non sono presenti dati')}
|
||||
{__('Non sono presenti dati')}
|
||||
</TableCell>
|
||||
</TableRow>);
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ export default class RecordsPage extends Page {
|
|||
|
||||
this.rows.forget(instance.id);
|
||||
m.redraw();
|
||||
await showSnackbar(this.__('Record eliminato!'), 4000);
|
||||
await showSnackbar(__('Record eliminato!'), 4000);
|
||||
});
|
||||
|
||||
loading.hide();
|
||||
|
@ -208,7 +208,7 @@ export default class RecordsPage extends Page {
|
|||
recordDialog() {
|
||||
return (
|
||||
<mwc-dialog id="add-record-dialog" class="record-dialog"
|
||||
heading={this.__('Aggiungi nuovo record')}
|
||||
heading={__('Aggiungi nuovo record')}
|
||||
style={`--mdc-dialog-max-width: ${this.recordDialogMaxWidth}`}>
|
||||
<form method="PUT">
|
||||
<text-field id="id" name="id" style="display: none;" data-default-value=""/>
|
||||
|
@ -243,11 +243,11 @@ export default class RecordsPage extends Page {
|
|||
})()}
|
||||
</form>
|
||||
|
||||
<LoadingButton type="submit" slot="primaryAction" label={this.__('Conferma')}/>
|
||||
<LoadingButton type="submit" slot="primaryAction" label={__('Conferma')}/>
|
||||
<mwc-button slot="secondaryAction" dialogAction="cancel">
|
||||
{this.__('Annulla')}
|
||||
{__('Annulla')}
|
||||
</mwc-button>
|
||||
<mwc-button id="delete-button" slot="secondaryAction" label={this.__('Elimina')}
|
||||
<mwc-button id="delete-button" slot="secondaryAction" label={__('Elimina')}
|
||||
style="--mdc-theme-primary: var(--mdc-theme-error, red); float: left; display: none;">
|
||||
<Mdi icon="delete-outline" slot="icon"/>
|
||||
</mwc-button>
|
||||
|
@ -258,9 +258,9 @@ export default class RecordsPage extends Page {
|
|||
deleteRecordDialog(): Children {
|
||||
return (
|
||||
<mwc-dialog id="confirm-delete-record-dialog">
|
||||
<p>{this.__('Sei sicuro di voler eliminare questo record?')}</p>
|
||||
<LoadingButton id="confirm-button" slot="primaryAction" label={this.__('Sì')}/>
|
||||
<mwc-button slot="secondaryAction" dialogAction="discard" label={this.__('No')}/>
|
||||
<p>{__('Sei sicuro di voler eliminare questo record?')}</p>
|
||||
<LoadingButton id="confirm-button" slot="primaryAction" label={__('Sì')}/>
|
||||
<mwc-button slot="secondaryAction" dialogAction="discard" label={__('No')}/>
|
||||
</mwc-dialog>
|
||||
);
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ export default class RecordsPage extends Page {
|
|||
</TableBody>
|
||||
</DataTable>
|
||||
|
||||
<mwc-fab id="add-record" label={this.__('Aggiungi')} class="sticky">
|
||||
<mwc-fab id="add-record" label={__('Aggiungi')} class="sticky">
|
||||
<Mdi icon="plus" slot="icon"/>
|
||||
</mwc-fab>
|
||||
{this.recordDialog()}
|
||||
|
@ -342,11 +342,11 @@ export default class RecordsPage extends Page {
|
|||
this.rows.put(model.id, model);
|
||||
|
||||
m.redraw();
|
||||
await showSnackbar(this.__('Record salvato'), 4000);
|
||||
await showSnackbar(__('Record salvato'), 4000);
|
||||
}
|
||||
} else {
|
||||
loading.hide();
|
||||
await showSnackbar(this.__('Campi non validi. Controlla i dati inseriti'));
|
||||
await showSnackbar(__('Campi non validi. Controlla i dati inseriti'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@ export function extend(proto, methods, callback) {
|
|||
for (const method of allMethods) {
|
||||
const original = proto[method];
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
proto[method] = function (...arguments_) {
|
||||
const value = original ? original.apply(this, arguments_) : undefined;
|
||||
|
||||
|
@ -79,7 +78,6 @@ export function override(object, methods, newMethod) {
|
|||
for (const method of allMethods) {
|
||||
const original = object[method];
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
object[method] = function (...arguments_) {
|
||||
return Reflect.apply(newMethod, this, [original.bind(this), ...arguments_]);
|
||||
};
|
||||
|
|
|
@ -51,74 +51,74 @@ export default class SetupPage extends Page {
|
|||
view(vnode) {
|
||||
const examplesTexts = collect();
|
||||
for (const example of ['localhost', 'root', 'mysql', 'openstamanager']) {
|
||||
examplesTexts.put(example, this.__('Esempio: :example', {example}));
|
||||
examplesTexts.put(example, __('Esempio: :example', {example}));
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card outlined className="center" style="width: 85%;">
|
||||
<Content>
|
||||
<img src={logoUrl} className="center" alt={this.__('OpenSTAManager')} />
|
||||
<img src={logoUrl} className="center" alt={__('OpenSTAManager')} />
|
||||
<LayoutGrid>
|
||||
<Row>
|
||||
<Cell columnspan-desktop="8">
|
||||
<h2>{this.__('Benvenuto in :name!', {name: <strong>{this.__('OpenSTAManager')}</strong>})}</h2>
|
||||
<p>{this.__('Puoi procedere alla configurazione tecnica del software attraverso i '
|
||||
<h2>{__('Benvenuto in :name!', {name: <strong>{__('OpenSTAManager')}</strong>})}</h2>
|
||||
<p>{__('Puoi procedere alla configurazione tecnica del software attraverso i '
|
||||
+ 'parametri seguenti, che potranno essere corretti secondo necessità tramite il file .env.')}<br/>
|
||||
{this.__("Se necessiti supporto puoi contattarci tramite l':contactLink o tramite il nostro :forumLink.", {
|
||||
{__("Se necessiti supporto puoi contattarci tramite l':contactLink o tramite il nostro :forumLink.", {
|
||||
// eslint-disable-next-line no-secrets/no-secrets
|
||||
contactLink: <a href="https://www.openstamanager.com/contattaci/?subject=Assistenza%20installazione%20OSM">{this.__('assistenza ufficiale')}</a>,
|
||||
forumLink: <a href="https://forum.openstamanager.com">{this.__('forum')}</a>
|
||||
contactLink: <a href="https://www.openstamanager.com/contattaci/?subject=Assistenza%20installazione%20OSM">{__('assistenza ufficiale')}</a>,
|
||||
forumLink: <a href="https://forum.openstamanager.com">{__('forum')}</a>
|
||||
})}</p>
|
||||
<h4>{this.__('Formato date')}</h4>
|
||||
<h4>{__('Formato date')}</h4>
|
||||
<small>
|
||||
{this.__('I formati sono impostabili attraverso lo standard previsto da :link.',
|
||||
{__('I formati sono impostabili attraverso lo standard previsto da :link.',
|
||||
{link: <a href="https://www.php.net/manual/en/function.date.php#refsect1-function.date-parameters">PHP</a>})
|
||||
}
|
||||
</small>
|
||||
<Row style="margin-top: 8px;">
|
||||
<Cell>
|
||||
<text-field name="timestamp_format" label={this.__('Formato data lunga')}
|
||||
<text-field name="timestamp_format" label={__('Formato data lunga')}
|
||||
required value="d/m/Y H:i">
|
||||
<Mdi icon="calendar-clock" slot="icon"/>
|
||||
</text-field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<text-field name="date_format" label={this.__('Formato data corta')}
|
||||
<text-field name="date_format" label={__('Formato data corta')}
|
||||
required value="d/m/Y">
|
||||
<Mdi icon="calendar-month-outline" slot="icon"/>
|
||||
</text-field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<text-field name="time_format" label={this.__('Formato orario')} required
|
||||
<text-field name="time_format" label={__('Formato orario')} required
|
||||
value="H:i">
|
||||
<Mdi icon="clock-outline" slot="icon"/>
|
||||
</text-field>
|
||||
</Cell>
|
||||
</Row>
|
||||
<hr/>
|
||||
<h4>{this.__('Database')}</h4>
|
||||
<h4>{__('Database')}</h4>
|
||||
<Row>
|
||||
<Cell columnspan="4">
|
||||
<text-field name="host" label={this.__('Host')} required
|
||||
<text-field name="host" label={__('Host')} required
|
||||
helper={examplesTexts.get('localhost')}>
|
||||
<Mdi icon="server-network" slot="icon"/>
|
||||
</text-field>
|
||||
</Cell>
|
||||
<Cell columnspan="4">
|
||||
<text-field name="username" label={this.__('Nome utente')} required
|
||||
<text-field name="username" label={__('Nome utente')} required
|
||||
helper={examplesTexts.get('root')}>
|
||||
<Mdi icon="account-outline" slot="icon"/>
|
||||
</text-field>
|
||||
</Cell>
|
||||
<Cell columnspan="4">
|
||||
<text-field name="password" label={this.__('Password')} required
|
||||
<text-field name="password" label={__('Password')} required
|
||||
helper={examplesTexts.get('mysql')}>
|
||||
<Mdi icon="lock-outline" slot="icon"/>
|
||||
</text-field>
|
||||
</Cell>
|
||||
<Cell columnspan="4">
|
||||
<text-field name="database_name" label={this.__('Nome database')} required
|
||||
<text-field name="database_name" label={__('Nome database')} required
|
||||
helper={examplesTexts.get('openstamanager')}>
|
||||
<Mdi icon="database-outline" slot="icon"/>
|
||||
</text-field>
|
||||
|
@ -127,38 +127,38 @@ export default class SetupPage extends Page {
|
|||
<hr/>
|
||||
<Row>
|
||||
<Cell>
|
||||
<small>{this.__('* Campi obbligatori')}</small>
|
||||
<small>{__('* Campi obbligatori')}</small>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<mwc-button raised label={this.__('Salva e installa')}>
|
||||
<mwc-button raised label={__('Salva e installa')}>
|
||||
<Mdi icon="check" slot="icon"/>
|
||||
</mwc-button>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<mwc-button outlined label={this.__('Testa il database')}>
|
||||
<mwc-button outlined label={__('Testa il database')}>
|
||||
<Mdi icon="test-tube" slot="icon"/>
|
||||
</mwc-button>
|
||||
</Cell>
|
||||
</Row>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<h4>{this.__('Lingua')}</h4>
|
||||
<h4>{__('Lingua')}</h4>
|
||||
<mwc-select>
|
||||
{this.languages()}
|
||||
</mwc-select>
|
||||
<hr />
|
||||
<h4>{this.__('Licenza')}</h4>
|
||||
<p>{this.__('OpenSTAManager è tutelato dalla licenza GPL 3.0, da accettare obbligatoriamente per poter utilizzare il gestionale.')}</p>
|
||||
<h4>{__('Licenza')}</h4>
|
||||
<p>{__('OpenSTAManager è tutelato dalla licenza GPL 3.0, da accettare obbligatoriamente per poter utilizzare il gestionale.')}</p>
|
||||
<mwc-textarea value={this.page.props.license} rows="15" cols="40" disabled />
|
||||
<Row style="margin-top: 5px;">
|
||||
<Cell columnspan-desktop="8" columnspan-tablet="8">
|
||||
<mwc-formfield label={this.__('Ho visionato e accetto la licenza')}>
|
||||
<mwc-formfield label={__('Ho visionato e accetto la licenza')}>
|
||||
<mwc-checkbox name="license_agreement"/>
|
||||
</mwc-formfield>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<a href="https://www.gnu.org/licenses/translations.en.html#GPL" target="_blank">
|
||||
<mwc-button label={this.__('Versioni tradotte')}>
|
||||
<mwc-button label={__('Versioni tradotte')}>
|
||||
<Mdi icon="license" slot="icon"/>
|
||||
</mwc-button>
|
||||
</a>
|
||||
|
@ -170,7 +170,7 @@ export default class SetupPage extends Page {
|
|||
</Content>
|
||||
</Card>
|
||||
<mwc-fab id="contrast-switcher" className="sticky contrast-light"
|
||||
label={this.__('Attiva/disattiva contrasto elevato')}>
|
||||
label={__('Attiva/disattiva contrasto elevato')}>
|
||||
<Mdi icon="contrast-circle" slot="icon" className="light-bg"/>
|
||||
</mwc-fab>
|
||||
</>
|
||||
|
|
|
@ -11,12 +11,15 @@ import {
|
|||
import $ from 'cash-dom';
|
||||
import m from 'mithril';
|
||||
|
||||
import {__} from './utils';
|
||||
|
||||
// Fix Mithril JSX durante la compilazione
|
||||
m.Fragment = '[';
|
||||
|
||||
// Variabili globali
|
||||
window.$ = $;
|
||||
window.m = m;
|
||||
window.__ = __;
|
||||
|
||||
InertiaProgress.init();
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
import type {Cash} from 'cash-dom/dist/cash';
|
||||
import {type Vnode} from 'mithril';
|
||||
import {sync as render} from 'mithril-node-render';
|
||||
|
||||
/**
|
||||
* Check if class/object A is the same as or a subclass of class B.
|
||||
|
@ -72,3 +74,45 @@ export function isFormValid(element: Cash | HTMLFontElement) {
|
|||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ritorna una traduzione
|
||||
*
|
||||
* @param {string|Vnode} key Stringa di cui prelevare la traduzione
|
||||
* @param {Object|boolean} replace Eventuali parametri da rimpiazzare.
|
||||
* Se il parametro è "true" (valore booleano), verrà ritornato il valore come stringa
|
||||
* (stesso funzionamento del parametro dedicato (sotto ↓))
|
||||
* @param {boolean} returnAsString Se impostato a "true" vien ritornata una stringa invece di
|
||||
* un Vnode di Mithril
|
||||
*
|
||||
* @returns {Vnode}
|
||||
*
|
||||
* @protected
|
||||
*/
|
||||
export function __(
|
||||
key: string | Vnode,
|
||||
replace: { [string]: string | Vnode | any } | boolean = {},
|
||||
returnAsString: boolean = false
|
||||
): Vnode | string {
|
||||
let translation = key;
|
||||
// noinspection JSUnresolvedVariable
|
||||
if (window.translations && window.translations[key]) {
|
||||
translation = window.translations[key];
|
||||
}
|
||||
|
||||
// Returns translation as string (no parameters replacement)
|
||||
if ((typeof replace === 'boolean' && replace) || (replace.length === 0 && !containsHTML(translation))) {
|
||||
return translation;
|
||||
}
|
||||
|
||||
for (const k of Object.keys(replace)) {
|
||||
// `'attrs' in replace[k]` checks if `replace[k]` is a Mithril Vnode
|
||||
translation = translation.replace(`:${k}`, ((typeof replace[k] === 'object' && 'attrs' in replace[k]) ? render(replace[k]) : replace[k]));
|
||||
}
|
||||
|
||||
if (returnAsString || !containsHTML(translation)) {
|
||||
return translation;
|
||||
}
|
||||
|
||||
return window.m.trust(translation);
|
||||
}
|
||||
|
|
|
@ -69,5 +69,8 @@
|
|||
@client
|
||||
|
||||
@vite('app')
|
||||
|
||||
@include('layouts.translations')
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -8,5 +8,7 @@
|
|||
|
||||
@client
|
||||
@vite('app')
|
||||
|
||||
@include('layouts.translations')
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
@php
|
||||
/** @var string $translations */
|
||||
$translations = cache('translations_' . app()->getLocale());
|
||||
@endphp
|
||||
<script>
|
||||
window.translations = JSON.parse('{!! $translations !!}')
|
||||
</script>
|
Loading…
Reference in New Issue