mirror of
https://github.com/devfake/flox.git
synced 2024-11-24 02:52:28 +01:00
add language translations for flox
This commit is contained in:
parent
c4b836f43a
commit
2e8e41a4be
@ -59,7 +59,11 @@ Export and import can also be used for the update of flox itself. Export your mo
|
||||
|
||||
### Translation
|
||||
|
||||
All movie titles are in english by default. You can change your language by setting `TRANSLATION` in `backend/.env`. The most commons are `DE`, `IT`, `FR`, `ES` and `RU`. You can try to use your language code. If there isn't a translation for your language, the english title will be used.
|
||||
All movie titles are in english by default. You can change your language by setting `TRANSLATION` in `backend/.env`. The most commons are `DE`, `IT`, `FR`, `ES` and `RU`. You can try to use your language code.
|
||||
|
||||
This will also affect the language of you website. See in `client/resources/languages` if your language is supported. Pull requests are welcome :)
|
||||
|
||||
If there isn't a translation for your language, english will be used.
|
||||
|
||||
### Better Search
|
||||
|
||||
|
16
backend/app/Http/Controllers/HomeController.php
Normal file
16
backend/app/Http/Controllers/HomeController.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Services\Storage;
|
||||
|
||||
class HomeController {
|
||||
|
||||
public function app($uri = null, Storage $storage)
|
||||
{
|
||||
$language = $storage->parseLanguage();
|
||||
|
||||
return view('app')
|
||||
->withLang($language);
|
||||
}
|
||||
}
|
@ -38,4 +38,22 @@
|
||||
{
|
||||
LaravelStorage::delete($poster);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse language file.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function parseLanguage()
|
||||
{
|
||||
$alternative = config('app.TRANSLATION') ?: 'EN';
|
||||
$filename = strtolower($alternative) . '.json';
|
||||
|
||||
// Get english fallback
|
||||
if( ! LaravelStorage::disk('languages')->exists($filename)) {
|
||||
$filename = 'en.json';
|
||||
}
|
||||
|
||||
return LaravelStorage::disk('languages')->get($filename);
|
||||
}
|
||||
}
|
@ -53,6 +53,11 @@
|
||||
'root' => base_path('../public/exports'),
|
||||
],
|
||||
|
||||
'languages' => [
|
||||
'driver' => 'local',
|
||||
'root' => base_path('../client/resources/languages'),
|
||||
],
|
||||
|
||||
'public' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app/public'),
|
||||
|
@ -30,6 +30,4 @@
|
||||
});
|
||||
});
|
||||
|
||||
Route::get('/{uri?}', function($uri = null) {
|
||||
return view('app');
|
||||
})->where('uri', '(.*)');
|
||||
Route::get('/{uri?}', 'HomeController@app')->where('uri', '(.*)');
|
||||
|
@ -7,10 +7,10 @@
|
||||
:date="displayDate"
|
||||
></Item>
|
||||
|
||||
<span class="nothing-found" v-if=" ! items.length">No Movies Found</span>
|
||||
<span class="nothing-found" v-if=" ! items.length">{{ lang('nothing found') }}</span>
|
||||
|
||||
<div class="load-more-wrap">
|
||||
<span class="load-more" v-if=" ! clickedMoreLoading && paginator" @click="loadMore()">Load More</span>
|
||||
<span class="load-more" v-if=" ! clickedMoreLoading && paginator" @click="loadMore()">{{ lang('load more') }}</span>
|
||||
<span class="loader" v-if="clickedMoreLoading"><i></i></span>
|
||||
</div>
|
||||
</div>
|
||||
@ -22,10 +22,13 @@
|
||||
<script>
|
||||
import Item from './Item.vue';
|
||||
import { mapActions, mapState } from 'vuex'
|
||||
import Helper from '../../helper';
|
||||
|
||||
import http from 'axios';
|
||||
|
||||
export default {
|
||||
mixins: [Helper],
|
||||
|
||||
created() {
|
||||
this.fetchData();
|
||||
this.fetchSettings();
|
||||
|
@ -9,8 +9,8 @@
|
||||
<span class="loader smallsize-loader" v-if="rated"><i></i></span>
|
||||
<i class="icon-add" v-if=" ! rated"></i>
|
||||
</span>
|
||||
<router-link :to="'/suggestions?for=' + localItem.tmdb_id" class="recommend-item">Suggestions</router-link>
|
||||
<span class="remove-item" v-if="localItem.rating && auth" @click="removeItem()">Delete Movie</span>
|
||||
<router-link :to="'/suggestions?for=' + localItem.tmdb_id" class="recommend-item">{{ lang('suggestions') }}</router-link>
|
||||
<span class="remove-item" v-if="localItem.rating && auth" @click="removeItem()">{{ lang('delete movie') }}</span>
|
||||
<img v-if="localItem.poster" :src="poster" class="item-image" width="185" height="278">
|
||||
<img v-if=" ! localItem.poster" :src="noImage" class="item-image" width="185" height="278">
|
||||
</div>
|
||||
@ -26,8 +26,11 @@
|
||||
|
||||
<script>
|
||||
import http from 'axios';
|
||||
import Helper from '../../helper';
|
||||
|
||||
export default {
|
||||
mixins: [Helper],
|
||||
|
||||
props: ['item', 'genre', 'date'],
|
||||
|
||||
data() {
|
||||
@ -111,7 +114,7 @@
|
||||
|
||||
removeItem() {
|
||||
if(this.auth) {
|
||||
const confirm = window.confirm('Are you sure?');
|
||||
const confirm = window.confirm(this.lang('confirm delete'));
|
||||
|
||||
if(confirm) {
|
||||
http.delete(`${config.api}/remove/${this.localItem.id}`).then(value => {
|
||||
|
@ -14,7 +14,7 @@
|
||||
:date="true"
|
||||
></Item>
|
||||
|
||||
<span class="nothing-found" v-if=" ! floxItems.length && ! tmdbItems.length">Nothing Found</span>
|
||||
<span class="nothing-found" v-if=" ! floxItems.length && ! tmdbItems.length">{{ lang('nothing found') }}</span>
|
||||
</div>
|
||||
|
||||
<span class="loader fullsize-loader" v-if="loading"><i></i></span>
|
||||
|
@ -2,36 +2,36 @@
|
||||
<main>
|
||||
<div class="wrap-content" v-if=" ! loading">
|
||||
<div class="settings-box">
|
||||
<span class="nothing-found">User</span>
|
||||
<span class="nothing-found">{{ lang('headline user') }}</span>
|
||||
<form class="login-form" @submit.prevent="editUser()">
|
||||
<input type="text" placeholder="Username" v-model="username">
|
||||
<input type="password" placeholder="Password" v-model="password" autocomplete="off">
|
||||
<span class="userdata-info">Leave the password field blank if you don't want to change it</span>
|
||||
<span class="userdata-changed"><span v-if="success">Successful changed</span></span>
|
||||
<input type="submit" value="Save">
|
||||
<input type="text" :placeholder="lang('username')" v-model="username">
|
||||
<input type="password" :placeholder="lang('password')" v-model="password" autocomplete="off">
|
||||
<span class="userdata-info">{{ lang('password message') }}</span>
|
||||
<span class="userdata-changed"><span v-if="success">{{ lang('success message') }}</span></span>
|
||||
<input type="submit" :value="lang('save button')">
|
||||
</form>
|
||||
</div>
|
||||
<div class="settings-box">
|
||||
<span class="nothing-found">Export / Import</span>
|
||||
<a :href="exportLink" class="export-btn">Export Movies</a>
|
||||
<span class="nothing-found">{{ lang('headline export import') }}</span>
|
||||
<a :href="exportLink" class="export-btn">{{ lang('export button') }}</a>
|
||||
<form class="login-form" @submit.prevent="importMovies()">
|
||||
<span class="import-info">OR</span>
|
||||
<span class="import-info">{{ lang('or divider') }}</span>
|
||||
<input type="file" @change="upload" class="file-btn" required>
|
||||
<span class="userdata-changed"><span v-if="uploadSuccess">Movies successful imported</span></span>
|
||||
<input type="submit" value="Import movies">
|
||||
<span class="userdata-changed"><span v-if="uploadSuccess">{{ lang('success import') }}</span></span>
|
||||
<input type="submit" :value="lang('import button')">
|
||||
</form>
|
||||
</div>
|
||||
<div class="settings-box">
|
||||
<span class="nothing-found">Misc</span>
|
||||
<button @click="updateGenre()" class="export-btn">Update Genre</button>
|
||||
<span class="import-info">OR</span>
|
||||
<button @click="syncScout()" class="export-btn">Sync Laravel Scout</button>
|
||||
<span class="import-info">OR</span>
|
||||
<span class="nothing-found">{{ lang('headline misc') }}</span>
|
||||
<button @click="updateGenre()" class="export-btn">{{ lang('update genre') }}</button>
|
||||
<span class="import-info">{{ lang('or divider') }}</span>
|
||||
<button @click="syncScout()" class="export-btn">{{ lang('sync scout') }}</button>
|
||||
<span class="import-info">{{ lang('or divider') }}</span>
|
||||
<div class="checkbox">
|
||||
<input type="checkbox" value="genre" v-model="displayGenre" id="genre" @change="updateSettings"><label for="genre">Display Genre</label>
|
||||
<input type="checkbox" value="genre" v-model="displayGenre" id="genre" @change="updateSettings"><label for="genre">{{ lang('display genre') }}</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<input type="checkbox" value="date" v-model="displayDate" id="date" @change="updateSettings"><label for="date">Display Date</label>
|
||||
<input type="checkbox" value="date" v-model="displayDate" id="date" @change="updateSettings"><label for="date">{{ lang('display date') }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -42,10 +42,13 @@
|
||||
|
||||
<script>
|
||||
import { mapState, mapMutations } from 'vuex';
|
||||
import Helper from '../../helper';
|
||||
|
||||
import http from 'axios';
|
||||
|
||||
export default {
|
||||
mixins: [Helper],
|
||||
|
||||
created() {
|
||||
this.fetchSettings();
|
||||
},
|
||||
@ -93,7 +96,7 @@
|
||||
|
||||
importMovies() {
|
||||
if(this.uploadedFile) {
|
||||
const confirm = window.confirm('All movies will be replaced. Be sure you have made an backup!');
|
||||
const confirm = window.confirm(this.lang('import warn'));
|
||||
|
||||
if(confirm) {
|
||||
this.SET_LOADING(true);
|
||||
|
@ -11,8 +11,8 @@
|
||||
<a class="icon-github" href="https://github.com/devfake/flox" target="_blank"></a>
|
||||
|
||||
<div class="sub-links">
|
||||
<a v-if="auth" :href="settings" class="login-btn">Settings</a>
|
||||
<a v-if="auth" :href="logout" class="login-btn">Logout</a>
|
||||
<a v-if="auth" :href="settings" class="login-btn">{{ lang('settings') }}</a>
|
||||
<a v-if="auth" :href="logout" class="login-btn">{{ lang('logout') }}</a>
|
||||
<a v-if=" ! auth" :href="login" class="login-btn">Login</a>
|
||||
</div>
|
||||
</div>
|
||||
@ -21,8 +21,11 @@
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
import Helper from '../helper';
|
||||
|
||||
export default {
|
||||
mixins: [Helper],
|
||||
|
||||
data() {
|
||||
return {
|
||||
auth: config.auth,
|
||||
|
@ -6,15 +6,15 @@
|
||||
</router-link>
|
||||
|
||||
<span class="sort-wrap">
|
||||
<i title="Last Seen" class="icon-sort-time" :class="{active: userFilter == 'created_at'}" @click="setUserFilter('created_at')"></i>
|
||||
<i title="Best Rated" class="icon-sort-star" :class="{active: userFilter == 'rating'}" @click="setUserFilter('rating')"></i>
|
||||
<span title="Toggle Color" class="icon-constrast" @click="toggleColorScheme()"><i></i></span>
|
||||
<i :title="lang('last seen')" class="icon-sort-time" :class="{active: userFilter == 'created_at'}" @click="setUserFilter('created_at')"></i>
|
||||
<i :title="lang('best rated')" class="icon-sort-star" :class="{active: userFilter == 'rating'}" @click="setUserFilter('rating')"></i>
|
||||
<span :title="lang('change color')" class="icon-constrast" @click="toggleColorScheme()"><i></i></span>
|
||||
</span>
|
||||
|
||||
<nav class="site-nav">
|
||||
<ul>
|
||||
<li><router-link to="/trending">Trending</router-link></li>
|
||||
<li><router-link to="/upcoming">Upcoming</router-link></li>
|
||||
<li><router-link to="/trending">{{ lang('trending') }}</router-link></li>
|
||||
<li><router-link to="/upcoming">{{ lang('upcoming') }}</router-link></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
@ -23,10 +23,13 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Helper from '../helper';
|
||||
import store from '../store/index';
|
||||
import { mapActions, mapMutations, mapState } from 'vuex'
|
||||
|
||||
export default {
|
||||
mixins: [Helper],
|
||||
|
||||
created() {
|
||||
this.checkForUserFilter();
|
||||
},
|
||||
|
@ -6,12 +6,12 @@
|
||||
<img src="../../../public/assets/img/logo-login.png" class="logo-login" alt="Flox" width="108" height="32">
|
||||
|
||||
<form class="login-form" @submit.prevent="login()">
|
||||
<input type="text" placeholder="Username" v-model="username" autofocus>
|
||||
<input type="password" placeholder="Password" v-model="password">
|
||||
<input type="text" :placeholder="lang('username')" v-model="username" autofocus>
|
||||
<input type="password" :placeholder="lang('password')" v-model="password">
|
||||
|
||||
<span class="login-error"><span v-if="error">Wrong username or password</span></span>
|
||||
<span class="login-error"><span v-if="error">{{ lang('login error') }}</span></span>
|
||||
|
||||
<input type="submit" :class="errorShake ? 'shake-horizontal shake-constant' : ''" value="Sign In">
|
||||
<input type="submit" :class="errorShake ? 'shake-horizontal shake-constant' : ''" :value="lang('login button')">
|
||||
</form>
|
||||
|
||||
</div>
|
||||
@ -20,8 +20,11 @@
|
||||
|
||||
<script>
|
||||
import http from 'axios';
|
||||
import Helper from '../helper';
|
||||
|
||||
export default {
|
||||
mixins: [Helper],
|
||||
|
||||
created() {
|
||||
document.body.className += ' dark';
|
||||
},
|
||||
|
@ -45,7 +45,8 @@
|
||||
},
|
||||
|
||||
placeholder() {
|
||||
return config.auth ? 'Search or add movie' : 'Search movie';
|
||||
//return config.auth ? 'Search or add movie' : 'Search movie';
|
||||
return config.auth ? this.lang('search or add') : this.lang('search');
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
import http from 'axios';
|
||||
http.defaults.headers.common['X-CSRF-TOKEN'] = document.querySelector('#token').getAttribute('content');
|
||||
|
||||
const {url, uri, auth, scoutDriver} = document.body.dataset;
|
||||
const {url, uri, auth, scoutDriver, language} = document.body.dataset;
|
||||
|
||||
const config = {
|
||||
uri,
|
||||
url,
|
||||
auth,
|
||||
language,
|
||||
scoutDriver,
|
||||
poster: url + '/assets/poster',
|
||||
posterTMDB: 'http://image.tmdb.org/t/p/w185',
|
||||
|
@ -18,6 +18,13 @@ export default {
|
||||
}
|
||||
|
||||
window.requestAnimationFrame(step);
|
||||
},
|
||||
|
||||
// Language helper
|
||||
lang(text) {
|
||||
const language = JSON.parse(config.language);
|
||||
|
||||
return language[text];
|
||||
}
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@
|
||||
data-uri="{{ config('app.CLIENT_URI') }}"
|
||||
data-scout-driver="{{ config('scout.driver') }}"
|
||||
data-auth="{{ Auth::check() }}"
|
||||
data-language="{{ $lang }}"
|
||||
class="{{ Auth::check() ? 'logged' : 'guest' }}"
|
||||
>
|
||||
|
||||
|
38
client/resources/languages/de.json
Normal file
38
client/resources/languages/de.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"username": "Benutzer",
|
||||
"password": "Passwort",
|
||||
"login button": "Einloggen",
|
||||
"login error": "Benutzer oder Passwort ist falsch",
|
||||
|
||||
"suggestions": "Vorschläge",
|
||||
"delete movie": "Film löschen",
|
||||
"confirm delete": "Wirklich löschen?",
|
||||
"search": "Film suchen",
|
||||
"search or add": "Film suchen oder hinzufügen",
|
||||
"load more": "Mehr anzeigen",
|
||||
"nothing found": "Nichts gefunden",
|
||||
|
||||
"trending": "Beliebt",
|
||||
"upcoming": "Kommend",
|
||||
"last seen": "Zuletzt gesehen",
|
||||
"best rated": "Am besten bewertet",
|
||||
"change color": "Farbmodus wechseln",
|
||||
|
||||
"settings": "Einstellungen",
|
||||
"logout": "Ausloggen",
|
||||
"headline user": "Benutzer",
|
||||
"headline export import": "Exportieren / Importieren",
|
||||
"headline misc": "Sonstiges",
|
||||
"save button": "Speichern",
|
||||
"password message": "Lasse das Passwort-Feld leer, wenn du es nicht ändern willst",
|
||||
"success message": "Erfolgreich gespeichert",
|
||||
"export button": "Exportieren",
|
||||
"import button": "Importieren",
|
||||
"or divider": "ODER",
|
||||
"update genre": "Genre updaten",
|
||||
"sync scout": "Sync Laravel Scout",
|
||||
"display genre": "Genre anzeigen",
|
||||
"display date": "Datum anzeigen",
|
||||
"success import": "Filme wurden erfolgreich importiert",
|
||||
"import warn": "Durch den Import werden alle Filme ersetzt. Erstelle vorher ein Backup!"
|
||||
}
|
38
client/resources/languages/en.json
Normal file
38
client/resources/languages/en.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"login button": "Login",
|
||||
"login error": "Wrong username or password",
|
||||
|
||||
"suggestions": "Suggestions",
|
||||
"delete movie": "Delete Movie",
|
||||
"confirm delete": "Are you sure?",
|
||||
"search": "Search movie",
|
||||
"search or add": "Search or add movie",
|
||||
"load more": "Load More",
|
||||
"nothing found": "Nothing found",
|
||||
|
||||
"trending": "Trending",
|
||||
"upcoming": "Upcoming",
|
||||
"last seen": "Last seen",
|
||||
"best rated": "Best rated",
|
||||
"change color": "Change colors",
|
||||
|
||||
"settings": "Settings",
|
||||
"logout": "Logout",
|
||||
"headline user": "User",
|
||||
"headline export import": "Export / Import",
|
||||
"headline misc": "Misc",
|
||||
"save button": "Save",
|
||||
"password message": "Leave the password field blank if you don't want to change it",
|
||||
"success message": "Successful changed",
|
||||
"export button": "Export movies",
|
||||
"import button": "Import movies",
|
||||
"or divider": "OR",
|
||||
"update genre": "Update genre",
|
||||
"sync scout": "Sync Laravel Scout",
|
||||
"display genre": "Display genre",
|
||||
"display date": "Display date",
|
||||
"success import": "Movies successful imported",
|
||||
"import warn": "All movies will be replaced. Be sure you have made an backup!"
|
||||
}
|
@ -3398,10 +3398,6 @@ vue-loader@^9.5.1:
|
||||
vue-template-compiler "^2.0.5"
|
||||
vue-template-es2015-compiler "^1.2.2"
|
||||
|
||||
vue-resource@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/vue-resource/-/vue-resource-1.0.3.tgz#8d52d0d8a9ed5f2ae704c68d530c84ceaf97be14"
|
||||
|
||||
vue-router@^2.0.0:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-2.0.3.tgz#444e246fd42d65a34dea6c3be8fde3315c4ba6f7"
|
||||
|
Loading…
Reference in New Issue
Block a user