Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GSoC 2024: Internationalization Implementation for Zimit Frontend #51

Closed
wants to merge 50 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
502fc8b
Add Vue I18n related dependencies for internationalization support
Onyx2406 Mar 10, 2024
d3c9e01
Update Vue components to support i18n
Onyx2406 Mar 10, 2024
586958e
Update Vue components to support i18n
Onyx2406 Mar 10, 2024
ca66949
Update Vue components to support i18n
Onyx2406 Mar 10, 2024
6f5ebb9
Update Vue components to support i18n
Onyx2406 Mar 10, 2024
4c004dd
Update Vue components to support i18n
Onyx2406 Mar 10, 2024
2c9d206
Update Vue components to support i18n
Onyx2406 Mar 10, 2024
1cff42f
Configure Vue I18n in main.js for dynamic translation loading
Onyx2406 Mar 10, 2024
4e3c249
Add files via upload
Onyx2406 Mar 10, 2024
aa02f60
Update NavBar.vue to i18n
Onyx2406 Mar 11, 2024
96944fe
Remove strings that are not used
Onyx2406 Mar 11, 2024
6e3b351
Remove strings that are not used
Onyx2406 Mar 11, 2024
fb67726
Update App.vue to i18n footer
Onyx2406 Mar 11, 2024
ea5114e
Update en.json
Onyx2406 Mar 11, 2024
647e9d0
Update fr.json
Onyx2406 Mar 11, 2024
9f29f54
Add qqq.json for translation instructions
Onyx2406 Mar 11, 2024
f493a1b
Add persian
Onyx2406 Mar 11, 2024
7e65335
Update NavBar.vue to add Persian in dropdown
Onyx2406 Mar 11, 2024
632384a
Fix footer translation, dropdown text.
Onyx2406 Mar 12, 2024
0993ce6
Resolve merge conflicts
Onyx2406 Mar 12, 2024
8553463
Remove AlertFeedback, SwitchButton translation strings
Onyx2406 Mar 12, 2024
0624a5e
Remove pers.json
Onyx2406 Mar 12, 2024
ae4afb3
Fix Faq content not showing and internationalize human_size_limit and…
Onyx2406 Mar 12, 2024
c393a5e
Change far.json to fa.json
Onyx2406 Mar 12, 2024
632a388
Change far.json to fa.json
Onyx2406 Mar 12, 2024
96a34d5
Load fa.json
Onyx2406 Mar 12, 2024
a33d73d
Add dynamic RTL support for Farsi language
Onyx2406 Mar 14, 2024
b15e046
i18 NewRequest and Request Component
Onyx2406 Mar 15, 2024
b5e7c88
Update Request.vue
Onyx2406 Mar 15, 2024
bb738ba
Fix footer text
Onyx2406 Apr 6, 2024
ea66868
Fix footer text
Onyx2406 Apr 6, 2024
5689c00
Merge branch 'my-dev-branch' into dev
Onyx2406 Apr 6, 2024
5ef22f5
Fix links not showing in FAQ entries
Onyx2406 Apr 6, 2024
9983a7a
Update en.json
Onyx2406 Apr 6, 2024
6bbd6df
Remove et --hard e3a1b35
Onyx2406 Apr 6, 2024
c6fe8af
Fix repeating strings in FAQ Entries
Onyx2406 Apr 6, 2024
e750147
Handle Pluralization
Onyx2406 Apr 6, 2024
f20692f
Remove sizeLimit in locales
Onyx2406 Apr 6, 2024
f576578
Update faq.vue
Onyx2406 Apr 6, 2024
6343c26
Updated en.json, including qqq.json. Standardized HTML code placement…
Onyx2406 Apr 8, 2024
ac1bb17
RTL Support for buttons of the FAQ
Onyx2406 Apr 8, 2024
d62680a
Logo to center, simplifies RTL Support CSS in FaqEntry.vue
Onyx2406 Apr 9, 2024
44bc447
CSS Refactor in FaqEntry.vue
Onyx2406 Apr 9, 2024
adcb06c
Keep only logo at the center, not the dropdown button
Onyx2406 Apr 11, 2024
284c7db
Fix - logo size was altered, now it remains constant
Onyx2406 Apr 11, 2024
1e7a70b
Remove class names in </Loading> , </header>
Onyx2406 Apr 11, 2024
597c786
Updated NavBar.vue
Onyx2406 Apr 12, 2024
68d5fae
Update NewRequest.vue
Onyx2406 Apr 12, 2024
0fafa07
Fix incorrect component import
Onyx2406 Apr 12, 2024
beb4986
Update main.js
Onyx2406 Apr 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"moment": "^2.29.1",
"sugar": "^2.0.6",
"vue": "^2.6.12",
"vue-i18n": "^8.0.0",
"vue-matomo": "^3.14.0-0",
"vue-router": "^3.4.9",
"vuex": "^3.5.1"
Expand Down
15 changes: 12 additions & 3 deletions ui/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
<NavBar />
<AlertFeedback />
<router-view />
<footer>
Powered by <a target="_blank" href="https://kiwix.org">Kiwix</a> and <a target="_blank" href="https://webrecorder.net">Webrecorder</a>, thanks to a <a target="_blank" href="https://www.mozilla.org/moss/">Mozilla Open-Source Support</a> Award <b-icon icon="heart-fill" style="color: rgb(234, 74, 170);" />
</footer>
<footer v-html="$t('footer.str')"></footer>
</div>
</template>

Expand All @@ -32,4 +30,15 @@ footer {
padding-top: 1em;
padding-bottom: 1em;
}

/* RTL styles */
[dir="rtl"] #app {
direction: rtl;
text-align: right;
}

[dir="rtl"] footer {
direction: rtl;
text-align: center; /* Keep footer text centered or change as needed */
}
</style>
49 changes: 29 additions & 20 deletions ui/src/components/Faq.vue
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
<template>
<div class="faq" role="tablist">
<FaqEntry
id="what-is-zim"
title="What is a Zim file?">
The Zim file format stores website content for <a target="_blank" href="https://en.wikipedia.org/wiki/Offline">offline</a> usage. It assembles the normal constituent of a website into a single archive, and compresses it so as to make it easier to save, share, and store.
<FaqEntry id="what-is-zim" :title="$t('faq.whatIsZim')">
<template v-slot:default>
<div v-html="$t('faq.whatIsZimDesc')"></div>
</template>
</FaqEntry>

<FaqEntry
id="how-to-read"
title="How do I read my Zim files?">
You will need a Zim file reader. This usually means <a target="_blank" href="https://kiwix.org/">Kiwix</a>, which is available on <a target="_blank" href="https://www.kiwix.org/en/download/">desktop computers, mobile devices, and more</a>. Currently only Kiwix-serve and Kiwix-Android can read all Zimit-generated files. If using Kiwix-Desktop for Microsoft Windows and GNU/Linux, then you will need to configure it as a Kiwix-serve instance in the settings. We expect most platforms to be upgraded by the end of 2021.
<FaqEntry id="how-to-read" :title="$t('faq.howToRead')">
<template v-slot:default>
<div v-html="$t('faq.howToReadDesc')"></div>
</template>
</FaqEntry>

<FaqEntry
id="missing-content"
title="The Zim file is incomplete or smaller than the original website">
Because of the very nature of this tool, we can’t leave it open for unlimited requests towards any website. That could be harmful both for our infrastructure, but also for the target websites. We currently enforce two limits: {{ human_size_limit }} file size and {{ human_time_limit }}.
<FaqEntry id="missing-content" :title="$t('faq.missingContent')">
<template v-slot:default>
{{ $t('faq.missingContentDesc', {
human_size_limit: human_size_limit,
human_time_limit: human_time_limit + ' ' + (human_time_limit === 1 ? $t('units.timeLimit.singular') : $t('units.timeLimit.plural'))
}) }}
</template>
</FaqEntry>

<FaqEntry
id="got-error"
title="I got an error message (no zim) or could not read a zim file">
Triple-check the URL you entered, and if it is still not working then open a bug ticket on <a target="_blank" href="https://github.com/openzim/zimit/issues">github</a>. Indicate the target website, the request number (it’s in the email you received), and the device you tried to open your zim file on.
<FaqEntry id="got-error" :title="$t('faq.gotError')">
<template v-slot:default>
<div v-html="$t('faq.gotErrorDesc')"></div>
</template>
</FaqEntry>
</div>
</template>
Expand All @@ -32,10 +35,16 @@

export default {
name: 'Faq',
components: {FaqEntry},
components: { FaqEntry },
computed: {
human_size_limit() { return `${parseInt(Constants.zimit_size_limit / 1073741824)} GiB`; },
human_time_limit() { return `${parseInt(Constants.zimit_time_limit / 3600)} hours`; },
human_size_limit() {
const sizeInGiB = parseInt(Constants.zimit_size_limit / 1073741824);
return `${sizeInGiB} GiB`;
},
human_time_limit() {
const timeInHours = parseInt(Constants.zimit_time_limit / 3600);
return timeInHours;
},
}
}
</script>
</script>
13 changes: 12 additions & 1 deletion ui/src/components/FaqEntry.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,18 @@
top: .5em;
right: .3rem;
}

/* Adjust for RTL by resetting 'right' and setting 'left' */
:root[dir="rtl"] .card-header .plus,
:root[dir="rtl"] .card-header .minus {
right: auto;
left: .3rem;
}

.card-header .collapsed .minus {
display: none;
}

.card-header .not-collapsed .plus {
display: none;
}
Expand All @@ -47,11 +56,13 @@
margin-bottom: 0 !important;
border-radius: 0;
}

.faq .card:not(:first-child) {
border-top: 0;
}

.card-header {
background-color: transparent;
border: 0;
}
</style>
</style>
16 changes: 8 additions & 8 deletions ui/src/components/Loading.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,18 @@
return this.$store.getters.loadingStatus.should_display;
},
loading_text() {
return this.$store.getters.loadingStatus.text;
return this.$store.getters.loadingStatus.text || this.$t('loading.loading');
}
}
}
</script>

<style type="text/css" scoped>
#main_loader {
color: white;
position: absolute;
top: 0;
left: 0;
padding: 0.4rem;
}
#main_loader {
color: white;
position: absolute;
top: 0;
left: 0;
padding: 0.4rem;
}
</style>
48 changes: 46 additions & 2 deletions ui/src/components/NavBar.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
<template>
<div>
<header>
<router-link :to="{ name: 'home' }"><img alt="Youzim.it logo" src="../assets/ZIMIT_LOGO_RGB.svg"></router-link>
<Loading/>
</header>

<div class="language-selector-container">
<select @change="changeLanguage($event)" class="language-selector">
<option value="en">English</option>
<option value="fr">Français</option>
<option value="fa">فارسی</option>
<!-- Add more languages here -->
</select>
</div>
</div>
</template>

<script>
Expand All @@ -11,14 +22,47 @@
export default {
name: 'NavBar',
components: {Loading},
methods: {
changeLanguage(event) {
this.$i18n.locale = event.target.value;
}
}
}
</script>

<style type="text/css" scoped="">
header {
display: inline-flex;
justify-content: center;
width: 100%;
text-align: center;
padding-top: 2em;
padding-bottom: 2em;
}
header img { max-width: 80%; width: 400px; }
</style>

header img {
max-width: 50vw;
width: 400px;
}

.language-selector-container {
position: absolute;
top: 2em;
right: 2em;
margin-left: auto;
}

.language-selector {
padding: .5rem 1rem;
border-radius: .25rem;
border: 1px solid #ced4da;
appearance: none;
background-color: #fff;
background-size: 16px 12px;
}

[dir='rtl'] .language-selector-container {
right: auto;
left: 2em;
}
</style>
32 changes: 15 additions & 17 deletions ui/src/components/NewRequest.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<template>
<div class="container">
<h1>Want an offline version of a website? Just <strong>Zim it</strong>!</h1>
<h1 v-html="$t('newRequest.heading')"></h1>

<b-form @submit.prevent="requestZim" v-if="editorReady">
<b-form-group>
<b-form-input
type="url"
id="new_url"
placeholder="Full URL of the website to convert"
:placeholder="$t('newRequest.urlPlaceholder')"
required="required"
v-model="form.url" />
</b-form-group>
Expand All @@ -16,23 +16,21 @@
<b-form-input
type="email"
id="new_email"
placeholder="Your e-mail to receive a download link. Address not kept"
:placeholder="$t('newRequest.emailPlaceholder')"
v-model="form.email" />
</b-form-group>


<b-form-group>
<b-button
pill
type="submit"
:disabled="!editorReady || !payload.url || busy"
variant="grey">
Let's Zim it!</b-button>
variant="grey">{{$t('newRequest.submit')}}</b-button>
<b-button
pill
size="sm"
:pressed.sync="showAdvanced"
variant="link-grey">advanced options</b-button>
variant="link-grey">{{$t('newRequest.advancedOptions')}}</b-button>
</b-form-group>

<div v-if="showAdvanced">
Expand Down Expand Up @@ -80,7 +78,7 @@
type="submit"
:disabled="!editorReady || !payload.url || busy"
variant="grey">
Let's Zim it!</b-button>
{{$t('newRequest.submit')}}</b-button>
</b-form-group>

</div>
Expand Down Expand Up @@ -156,14 +154,14 @@

if (field.type == "boolean") {
component = "switchbutton";
options = [{text: "True", value: true}, {text: "Not set", value: undefined}];
options = [{text: this.$t('newRequest.true'), value: true}, {text: this.$t('newRequest.notSet'), value: undefined}];
}

if (field.type == "string-enum") {
component = "b-form-select";
options = field.choices.map(function (option) { return {text: option, value: option}; });
options = field.choices.map(option => ({text: option, value: option}));
if (field.required != true) {
options.push({text: "Not set", value: undefined});
options.push({text: this.$t('newRequest.notSet'), value: undefined});
}
}

Expand All @@ -177,7 +175,7 @@
data_key: field.data_key,
required: field.required,
description: field.description,
placeholder: "Not set", //field.placeholder,
placeholder: this.$t('newRequest.notSet'), //field.placeholder,

component: component,
component_type: component_type,
Expand All @@ -202,7 +200,7 @@

let parent = this;
console.debug("fetching definition…");
parent.toggleLoader("fetching definition…");
parent.toggleLoader(this.$t('newRequest.fetchingDefinition'));
parent.queryAPI('get', Constants.zimfarm_webapi + '/offliners/zimit')
.then(function (response) {
let definition = response.data.filter(field => Constants.zimit_fields.indexOf(field.key) > -1);
Expand All @@ -211,7 +209,7 @@
if (on_success) { on_success(); }
})
.catch(function (error) {
if (on_error) { on_error(Constants.standardHTTPError(error.response)); }
if (on_error) { on_error(parent.$t('newRequest.standardHTTPError', { error: Constants.standardHTTPError(error.response) })); }
})
.then(function () {
parent.toggleLoader(false);
Expand All @@ -224,17 +222,17 @@
this.payload.flags = Object.filter(this.payload.flags, item => item!=="");
parent.busy = true;
let task_id = null;
parent.toggleLoader("Creating schedule…");
parent.toggleLoader(this.$t('newRequest.creatingSchedule'));
parent.queryAPI('post', Constants.zimitui_api + '/requests/', this.payload)
.then(function (response) {
if (response.data && response.data.id) {
task_id = response.data.id;
parent.redirectTo('request', {task_id: task_id});
} else
throw "Didn't receive task_id";
throw new Error(parent.$t('newRequest.noTaskIdReceived'));
})
.catch(function (error) {
parent.alertError("Unable to request ZIM creation:<br />" + Constants.standardHTTPError(error.response));
parent.alertError(parent.$t('newRequest.unableToRequestZIM', { error: Constants.standardHTTPError(error.response) }));
})
.then(function () {
parent.toggleLoader(false);
Expand Down
4 changes: 2 additions & 2 deletions ui/src/components/NotFound.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

<template>
<div class="container">
<h1>Not Found</h1>
<p>Sorry, this content was not found. Maybe you'd like to go back.</p>
<h1>{{ $t('notFound.heading') }}</h1>
<p>{{ $t('notFound.description') }}</p>
</div>
</template>

Expand Down
Loading
Loading