mirror of
https://github.com/sysadminsmedia/homebox.git
synced 2025-12-21 21:33:02 +01:00
Compare commits
89 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
02c0453ff3 | ||
|
|
09358aa5b2 | ||
|
|
dbe77ea19d | ||
|
|
85e5c7e8e7 | ||
|
|
3c273b370d | ||
|
|
343e56b440 | ||
|
|
3a949aee5a | ||
|
|
1601e52c9c | ||
|
|
760cc8e35c | ||
|
|
6051e1fb8b | ||
|
|
7b146947df | ||
|
|
5497a10f9f | ||
|
|
3e6f4b3657 | ||
|
|
7baf58ad61 | ||
|
|
d72437d18c | ||
|
|
ea57981953 | ||
|
|
c2d0cce02d | ||
|
|
9f7a119e95 | ||
|
|
0dacc97e99 | ||
|
|
52a44da56b | ||
|
|
7114f262c2 | ||
|
|
7647ea96d1 | ||
|
|
593da25cdb | ||
|
|
f22bce7ccb | ||
|
|
1688773bba | ||
|
|
b56b5d2400 | ||
|
|
33ee208071 | ||
|
|
fe880cc2c7 | ||
|
|
cffe57b74e | ||
|
|
66882d6fd9 | ||
|
|
050f22f051 | ||
|
|
7891af3a9a | ||
|
|
40cbccf50a | ||
|
|
0348da362c | ||
|
|
f0a3780f3a | ||
|
|
39163f3cfc | ||
|
|
43676ab407 | ||
|
|
639f795b9a | ||
|
|
fc95d2cab8 | ||
|
|
695b6d68e6 | ||
|
|
b6c265098d | ||
|
|
2a80d348bd | ||
|
|
c6542de93d | ||
|
|
5928678564 | ||
|
|
fac52ca122 | ||
|
|
e9d270269f | ||
|
|
0a4c5fbb28 | ||
|
|
2bfb0283d9 | ||
|
|
94e8aee36f | ||
|
|
8051956a2e | ||
|
|
c7020503be | ||
|
|
28edce96d9 | ||
|
|
b4481fcc84 | ||
|
|
2be2bebb4e | ||
|
|
d4bb8def62 | ||
|
|
7442cb01b7 | ||
|
|
95ba8275e8 | ||
|
|
2f4a0dd212 | ||
|
|
52a621e9ba | ||
|
|
1f77fad829 | ||
|
|
8d93a3f56e | ||
|
|
9c572e7ab2 | ||
|
|
1f15e74730 | ||
|
|
7570a04c02 | ||
|
|
fc2e89c448 | ||
|
|
be216ff7fe | ||
|
|
388208571b | ||
|
|
1891903007 | ||
|
|
41a7e73ff4 | ||
|
|
81d9fb0700 | ||
|
|
76312d6eb6 | ||
|
|
f31528c841 | ||
|
|
6d869fdece | ||
|
|
d0784a7773 | ||
|
|
791f843bc8 | ||
|
|
a0cdb231fd | ||
|
|
e0004842e6 | ||
|
|
fdbfa0e76f | ||
|
|
005516013f | ||
|
|
9ec3dd4b16 | ||
|
|
4dacf981a9 | ||
|
|
9f7b76b37d | ||
|
|
0d51558e74 | ||
|
|
236c257892 | ||
|
|
3540ce4297 | ||
|
|
0bcb155756 | ||
|
|
12219522ab | ||
|
|
13864997ab | ||
|
|
2ab2766534 |
@@ -49,6 +49,11 @@ Contributions are what make the open source community such an amazing place to l
|
|||||||
|
|
||||||
If you are not a coder, you can still contribute financially. Financial contributions help me prioritize working on this project over others and helps me know that there is a real demand for project development.
|
If you are not a coder, you can still contribute financially. Financial contributions help me prioritize working on this project over others and helps me know that there is a real demand for project development.
|
||||||
|
|
||||||
|
## Help us Translate
|
||||||
|
We want to make sure that Homebox is available in as many languages as possible. If you are interested in helping us translate Homebox, please help us via our [Weblate instance](https://translate.sysadminsmedia.com/projects/homebox/).
|
||||||
|
|
||||||
|
[](http://translate.sysadminsmedia.com/engage/homebox/)
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
- Original project by [@hay-kot](https://github.com/hay-kot)
|
- Original project by [@hay-kot](https://github.com/hay-kot)
|
||||||
|
|||||||
@@ -4,12 +4,6 @@ import (
|
|||||||
"embed"
|
"embed"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"mime"
|
|
||||||
"net/http"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/hay-kot/httpkit/errchain"
|
"github.com/hay-kot/httpkit/errchain"
|
||||||
httpSwagger "github.com/swaggo/http-swagger/v2" // http-swagger middleware
|
httpSwagger "github.com/swaggo/http-swagger/v2" // http-swagger middleware
|
||||||
@@ -19,6 +13,11 @@ import (
|
|||||||
_ "github.com/sysadminsmedia/homebox/backend/app/api/static/docs"
|
_ "github.com/sysadminsmedia/homebox/backend/app/api/static/docs"
|
||||||
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/authroles"
|
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/authroles"
|
||||||
"github.com/sysadminsmedia/homebox/backend/internal/data/repo"
|
"github.com/sysadminsmedia/homebox/backend/internal/data/repo"
|
||||||
|
"io"
|
||||||
|
"mime"
|
||||||
|
"net/http"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
const prefix = "/api"
|
const prefix = "/api"
|
||||||
|
|||||||
@@ -222,6 +222,7 @@ func (s *IOSheet) ReadItems(ctx context.Context, items []repo.ItemOut, GID uuid.
|
|||||||
SoldPrice: item.SoldPrice,
|
SoldPrice: item.SoldPrice,
|
||||||
SoldNotes: item.SoldNotes,
|
SoldNotes: item.SoldNotes,
|
||||||
|
|
||||||
|
Notes: item.Notes,
|
||||||
Fields: customFields,
|
Fields: customFields,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,9 +29,9 @@ func (tp *TemplateProps) Set(key, value string) {
|
|||||||
func DefaultTemplateData() TemplateProps {
|
func DefaultTemplateData() TemplateProps {
|
||||||
return TemplateProps{
|
return TemplateProps{
|
||||||
Defaults: TemplateDefaults{
|
Defaults: TemplateDefaults{
|
||||||
CompanyName: "Haybytes.com",
|
CompanyName: "sysadminsmedia.com",
|
||||||
CompanyAddress: "123 Main St, Anytown, CA 12345",
|
CompanyAddress: "123 Main St, Anytown, CA 12345",
|
||||||
CompanyURL: "https://haybytes.com",
|
CompanyURL: "https://sysadminsmedia.com",
|
||||||
ActivateAccountURL: "https://google.com",
|
ActivateAccountURL: "https://google.com",
|
||||||
UnsubscribeURL: "https://google.com",
|
UnsubscribeURL: "https://google.com",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export default defineConfig({
|
|||||||
description: "A simple home inventory management software",
|
description: "A simple home inventory management software",
|
||||||
lastUpdated: true,
|
lastUpdated: true,
|
||||||
sitemap: {
|
sitemap: {
|
||||||
hostname: 'https://homebox.sysadminsmedia.com',
|
hostname: 'https://homebox.software',
|
||||||
},
|
},
|
||||||
|
|
||||||
locales: {
|
locales: {
|
||||||
|
|||||||
@@ -47,24 +47,28 @@ type checking `task ui:check`
|
|||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
We use [Vitepress](https://vitepress.dev/) for the web documentation of homebox. Anyone is welcome to contribute the documentation if they wish.
|
We use [Vitepress](https://vitepress.dev/) for the web documentation of homebox. Anyone is welcome to contribute the documentation if they wish.
|
||||||
Anyone is welcome to contribute the documentation if they wish. For documentation contributions, you only need Node.js and PNPM.
|
For documentation contributions, you only need Node.js and PNPM.
|
||||||
|
|
||||||
::: info Notes
|
::: info Notes
|
||||||
- Languages are separated by folder (e.g `/en`, `/fr`, etc.)
|
- Languages are separated by folder (e.g `/en`, `/fr`, etc.)
|
||||||
- The Sidebar must be updated on a per language basis
|
- The Sidebar must be updated on a per language basis
|
||||||
+ The Sidebar must be updated on a per-language basis
|
- Each language's files can be named independently (slugs can match the language)
|
||||||
- Each languages files can be named independently (slugs can match the language)
|
|
||||||
- The `public/_redirects` file is used to redirect the default to english
|
- The `public/_redirects` file is used to redirect the default to english
|
||||||
- Redirects can also be configured per language by adding `Language=` after the redirect code
|
- Redirects can also be configured per language by adding `Language=` after the redirect code
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
## Translations
|
||||||
|
We use our own [Weblate instance](https://translate.sysadminsmedia.com/projects/homebox/) for translations. If you would like to help translate Homebox, please visit the Weblate instance and help us translate the project.
|
||||||
|
|
||||||
|
[](http://translate.sysadminsmedia.com/engage/homebox/)
|
||||||
|
|
||||||
## Branch Flow
|
## Branch Flow
|
||||||
We use the `main` branch as the development branch. All PRs should be made to the `main` branch form a feature branch.
|
We use the `main` branch as the development branch. All PRs should be made to the `main` branch from a feature branch.
|
||||||
To create a pull request you can use the following steps:
|
To create a pull request you can use the following steps:
|
||||||
|
|
||||||
1. Fork the repo and create a new branch from `main`
|
1. Fork the repo and create a new branch from `main`
|
||||||
2. If you added code that should be tested, add tests
|
2. If you added code that should be tested, add tests
|
||||||
3. If you've changed APIs update the documentation
|
3. If you've changed APIs, update the documentation
|
||||||
4. Ensure that the test suite and linters pass
|
4. Ensure that the test suite and linters pass
|
||||||
5. Create your PR
|
5. Create your PR
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ Homebox provides the option to auto-set asset IDs, this is the default behavior.
|
|||||||
|
|
||||||
Example ID: `000-001`
|
Example ID: `000-001`
|
||||||
|
|
||||||
|
To search for an Asset ID: type `#` in the search bar followed by the ID you're searching for, e.g. `#000-001`.
|
||||||
|
|
||||||
Asset IDs are partially managed by Homebox, but have a flexible implementation to allow for unique use cases. IDs are non-unique at the database level, so there is nothing stopping a user from manually setting duplicate IDs for various items. There are two recommended approaches to manage Asset IDs:
|
Asset IDs are partially managed by Homebox, but have a flexible implementation to allow for unique use cases. IDs are non-unique at the database level, so there is nothing stopping a user from manually setting duplicate IDs for various items. There are two recommended approaches to manage Asset IDs:
|
||||||
|
|
||||||
### 1. Auto Incrementing IDs
|
### 1. Auto Incrementing IDs
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<BaseModal v-model="dialog">
|
<BaseModal v-model="dialog">
|
||||||
<template #title> Import CSV File </template>
|
<template #title> {{ $t("components.app.import_dialog.title") }} </template>
|
||||||
<p>
|
<p>
|
||||||
Import a CSV file containing your items, labels, and locations. See documentation for more information on the
|
{{ $t("components.app.import_dialog.description") }}
|
||||||
required format.
|
|
||||||
</p>
|
</p>
|
||||||
<div class="alert alert-warning shadow-lg mt-4">
|
<div class="alert alert-warning shadow-lg mt-4">
|
||||||
<div>
|
<div>
|
||||||
@@ -21,8 +20,7 @@
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
<span class="text-sm">
|
<span class="text-sm">
|
||||||
Behavior for imports with existing import_refs has changed. If an import_ref is present in the CSV file, the
|
{{ $t("components.app.import_dialog.change_warning") }}
|
||||||
item will be updated with the values in the CSV file.
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -33,7 +31,7 @@
|
|||||||
|
|
||||||
<BaseButton type="button" @click="uploadCsv">
|
<BaseButton type="button" @click="uploadCsv">
|
||||||
<MdiUpload class="h-5 w-5 mr-2" />
|
<MdiUpload class="h-5 w-5 mr-2" />
|
||||||
Upload
|
{{ $t("components.app.import_dialog.upload") }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<p class="text-center pt-4 -mb-5">
|
<p class="text-center pt-4 -mb-5">
|
||||||
{{ importCsv?.name }}
|
{{ importCsv?.name }}
|
||||||
@@ -41,7 +39,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal-action">
|
<div class="modal-action">
|
||||||
<BaseButton type="submit" :disabled="!importCsv"> Submit </BaseButton>
|
<BaseButton type="submit" :disabled="!importCsv"> {{ $t("global.submit") }} </BaseButton>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
|
|||||||
@@ -1,19 +1,25 @@
|
|||||||
<template>
|
<template>
|
||||||
<BaseModal v-model="modal">
|
<BaseModal v-model="modal">
|
||||||
<template #title> Create Item </template>
|
<template #title> {{ $t("components.item.create_modal.title") }} </template>
|
||||||
<form @submit.prevent="create()">
|
<form @submit.prevent="create()">
|
||||||
<LocationSelector v-model="form.location" />
|
<LocationSelector v-model="form.location" />
|
||||||
<FormTextField ref="nameInput" v-model="form.name" :trigger-focus="focused" :autofocus="true" label="Item Name" />
|
<FormTextField ref="nameInput" v-model="form.name" :trigger-focus="focused" :autofocus="true" label="Item Name" />
|
||||||
<FormTextArea v-model="form.description" label="Item Description" />
|
<FormTextArea v-model="form.description" label="Item Description" />
|
||||||
<FormMultiselect v-model="form.labels" label="Labels" :items="labels ?? []" />
|
<FormMultiselect v-model="form.labels" label="Labels" :items="labels ?? []" />
|
||||||
|
|
||||||
|
|
||||||
<div class="modal-action">
|
<div class="modal-action">
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
|
<div>
|
||||||
|
<label for="photo" class="btn">{{ $t("components.item.create_modal.photo_button") }}</label>
|
||||||
|
<input type="file" accept="image/*" @change="previewImage" style="visibility:hidden;" id="photo">
|
||||||
|
</div>
|
||||||
<BaseButton class="rounded-r-none" :loading="loading" type="submit">
|
<BaseButton class="rounded-r-none" :loading="loading" type="submit">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<MdiPackageVariant class="swap-off h-5 w-5" />
|
<MdiPackageVariant class="swap-off h-5 w-5" />
|
||||||
<MdiPackageVariantClosed class="swap-on h-5 w-5" />
|
<MdiPackageVariantClosed class="swap-on h-5 w-5" />
|
||||||
</template>
|
</template>
|
||||||
Create
|
{{ $t("global.create") }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<div class="dropdown dropdown-top">
|
<div class="dropdown dropdown-top">
|
||||||
<label tabindex="0" class="btn rounded-l-none rounded-r-xl">
|
<label tabindex="0" class="btn rounded-l-none rounded-r-xl">
|
||||||
@@ -21,12 +27,23 @@
|
|||||||
</label>
|
</label>
|
||||||
<ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-64 right-0">
|
<ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-64 right-0">
|
||||||
<li>
|
<li>
|
||||||
<button type="button" @click="create(false)">Create and Add Another</button>
|
<button type="button" @click="create(false)">{{ $t("global.create_and_add") }}</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- photo preview area is AFTER the create button, to avoid pushing the button below the screen on small displays -->
|
||||||
|
<div class="border-t border-gray-300 p-4">
|
||||||
|
<template v-if="form.preview">
|
||||||
|
<p class="mb-0">file name: {{ form.photo.name }}</p>
|
||||||
|
<img :src="form.preview" class="h-[100px] w-full object-cover rounded-t shadow-sm border-gray-300" />
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
<p class="text-sm text-center mt-4">
|
<p class="text-sm text-center mt-4">
|
||||||
use <kbd class="kbd kbd-xs">Shift</kbd> + <kbd class="kbd kbd-xs"> Enter </kbd> to create and add another
|
use <kbd class="kbd kbd-xs">Shift</kbd> + <kbd class="kbd kbd-xs"> Enter </kbd> to create and add another
|
||||||
@@ -41,6 +58,7 @@
|
|||||||
import MdiPackageVariant from "~icons/mdi/package-variant";
|
import MdiPackageVariant from "~icons/mdi/package-variant";
|
||||||
import MdiPackageVariantClosed from "~icons/mdi/package-variant-closed";
|
import MdiPackageVariantClosed from "~icons/mdi/package-variant-closed";
|
||||||
import MdiChevronDown from "~icons/mdi/chevron-down";
|
import MdiChevronDown from "~icons/mdi/chevron-down";
|
||||||
|
import { AttachmentTypes } from "~~/lib/api/types/non-generated";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
@@ -85,10 +103,40 @@
|
|||||||
description: "",
|
description: "",
|
||||||
color: "", // Future!
|
color: "", // Future!
|
||||||
labels: [] as LabelOut[],
|
labels: [] as LabelOut[],
|
||||||
|
preview: null,
|
||||||
|
photo: null
|
||||||
});
|
});
|
||||||
|
|
||||||
const { shift } = useMagicKeys();
|
const { shift } = useMagicKeys();
|
||||||
|
|
||||||
|
function previewImage(event) {
|
||||||
|
var input = event.target;
|
||||||
|
if (input.files) {
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.onload = (e) => {
|
||||||
|
form.preview = e.target.result;
|
||||||
|
}
|
||||||
|
form.photo=input.files[0];
|
||||||
|
reader.readAsDataURL(input.files[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function uploadImage(e: Event) {
|
||||||
|
const files = (e.target as HTMLInputElement).files;
|
||||||
|
if (!files || !files.item(0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const first = files.item(0);
|
||||||
|
if (!first) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadAttachment([first], null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
whenever(
|
whenever(
|
||||||
() => modal.value,
|
() => modal.value,
|
||||||
() => {
|
() => {
|
||||||
@@ -133,10 +181,25 @@
|
|||||||
|
|
||||||
toast.success("Item created");
|
toast.success("Item created");
|
||||||
|
|
||||||
|
// if the photo was provided, upload it
|
||||||
|
if(form.photo){
|
||||||
|
const { data2, error } = await api.items.attachments.add(data.id, form.photo, form.photo.name, AttachmentTypes.Photo);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
toast.error("Failed to upload Photo");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
toast.success("Photo uploaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Reset
|
// Reset
|
||||||
form.name = "";
|
form.name = "";
|
||||||
form.description = "";
|
form.description = "";
|
||||||
form.color = "";
|
form.color = "";
|
||||||
|
form.preview = null;
|
||||||
|
form.photo = null;
|
||||||
focused.value = false;
|
focused.value = false;
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<section>
|
<section>
|
||||||
<BaseSectionHeader class="mb-2 flex justify-between items-center">
|
<BaseSectionHeader class="mb-2 flex justify-between items-center">
|
||||||
Items
|
{{ $t("components.item.view.selectable.items") }}
|
||||||
<template #description>
|
<template #description>
|
||||||
<div v-if="!viewSet" class="dropdown dropdown-hover dropdown-left">
|
<div v-if="!viewSet" class="dropdown dropdown-hover dropdown-left">
|
||||||
<label tabindex="0" class="btn btn-ghost m-1">
|
<label tabindex="0" class="btn btn-ghost m-1">
|
||||||
@@ -39,13 +39,13 @@
|
|||||||
<li>
|
<li>
|
||||||
<button @click="setViewPreference('card')">
|
<button @click="setViewPreference('card')">
|
||||||
<MdiCardTextOutline class="h-5 w-5" />
|
<MdiCardTextOutline class="h-5 w-5" />
|
||||||
Card
|
{{ $t("components.item.view.selectable.card") }}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button @click="setViewPreference('table')">
|
<button @click="setViewPreference('table')">
|
||||||
<MdiTable class="h-5 w-5" />
|
<MdiTable class="h-5 w-5" />
|
||||||
Table
|
{{ $t("components.item.view.selectable.table") }}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
|
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
|
||||||
<ItemCard v-for="item in items" :key="item.id" :item="item" />
|
<ItemCard v-for="item in items" :key="item.id" :item="item" />
|
||||||
<div class="first:block hidden text-lg">No Items to Display</div>
|
<div class="first:block hidden text-lg">{{ $t("components.item.view.selectable.no_items") }}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<BaseModal v-model="modal">
|
<BaseModal v-model="modal">
|
||||||
<template #title> Create Label </template>
|
<template #title>{{ $t("components.label.create_modal.title") }}</template>
|
||||||
<form @submit.prevent="create()">
|
<form @submit.prevent="create()">
|
||||||
<FormTextField
|
<FormTextField
|
||||||
ref="locationNameRef"
|
ref="locationNameRef"
|
||||||
@@ -12,14 +12,14 @@
|
|||||||
<FormTextArea v-model="form.description" label="Label Description" />
|
<FormTextArea v-model="form.description" label="Label Description" />
|
||||||
<div class="modal-action">
|
<div class="modal-action">
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
<BaseButton class="rounded-r-none" :loading="loading" type="submit"> Create </BaseButton>
|
<BaseButton class="rounded-r-none" :loading="loading" type="submit"> {{ $t("global.create") }} </BaseButton>
|
||||||
<div class="dropdown dropdown-top">
|
<div class="dropdown dropdown-top">
|
||||||
<label tabindex="0" class="btn rounded-l-none rounded-r-xl">
|
<label tabindex="0" class="btn rounded-l-none rounded-r-xl">
|
||||||
<MdiChevronDown class="h-5 w-5" />
|
<MdiChevronDown class="h-5 w-5" />
|
||||||
</label>
|
</label>
|
||||||
<ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-64 right-0">
|
<ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-64 right-0">
|
||||||
<li>
|
<li>
|
||||||
<button type="button" @click="create(false)">Create and Add Another</button>
|
<button type="button" @click="create(false)">{{ $t("global.create_and_add") }}</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<BaseModal v-model="modal">
|
<BaseModal v-model="modal">
|
||||||
<template #title> Create Location </template>
|
<template #title>{{ $t("components.location.create_modal.title") }}</template>
|
||||||
<form @submit.prevent="create()">
|
<form @submit.prevent="create()">
|
||||||
<FormTextField
|
<FormTextField
|
||||||
ref="locationNameRef"
|
ref="locationNameRef"
|
||||||
@@ -13,14 +13,14 @@
|
|||||||
<LocationSelector v-model="form.parent" />
|
<LocationSelector v-model="form.parent" />
|
||||||
<div class="modal-action">
|
<div class="modal-action">
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
<BaseButton class="rounded-r-none" type="submit" :loading="loading"> Create </BaseButton>
|
<BaseButton class="rounded-r-none" type="submit" :loading="loading">{{ $t("global.create") }}</BaseButton>
|
||||||
<div class="dropdown dropdown-top">
|
<div class="dropdown dropdown-top">
|
||||||
<label tabindex="0" class="btn rounded-l-none rounded-r-xl">
|
<label tabindex="0" class="btn rounded-l-none rounded-r-xl">
|
||||||
<MdiChevronDown class="h-5 w-5" />
|
<MdiChevronDown class="h-5 w-5" />
|
||||||
</label>
|
</label>
|
||||||
<ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-64 right-0">
|
<ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-64 right-0">
|
||||||
<li>
|
<li>
|
||||||
<button type="button" @click="create(false)">Create and Add Another</button>
|
<button type="button" @click="create(false)">{{ $t("global.create_and_add") }}</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<BaseModal v-model="isRevealed" readonly @cancel="cancel(false)">
|
<BaseModal v-model="isRevealed" readonly @cancel="cancel(false)">
|
||||||
<template #title> Confirm </template>
|
<template #title> {{ $t("global.confirm") }} </template>
|
||||||
<div>
|
<div>
|
||||||
<p>{{ text }}</p>
|
<p>{{ text }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-action">
|
<div class="modal-action">
|
||||||
<BaseButton type="submit" @click="confirm(true)"> Confirm </BaseButton>
|
<BaseButton type="submit" @click="confirm(true)"> {{ $t("global.confirm") }} </BaseButton>
|
||||||
</div>
|
</div>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
</slot>
|
</slot>
|
||||||
<div tabindex="0" class="card compact dropdown-content shadow-lg bg-base-100 rounded-box w-64">
|
<div tabindex="0" class="card compact dropdown-content shadow-lg bg-base-100 rounded-box w-64">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h2 class="text-center">Page URL</h2>
|
<h2 class="text-center">{{ $t("components.global.page_qr_code.page_url") }}</h2>
|
||||||
<img :src="getQRCodeUrl()" />
|
<img :src="getQRCodeUrl()" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="py-4">
|
<div class="py-4">
|
||||||
<p class="text-sm">Password Strength: {{ message }}</p>
|
<p class="text-sm">{{ $t("components.global.password_score.password_strength") }}: {{ message }}</p>
|
||||||
<progress
|
<progress
|
||||||
class="progress w-full progress-bar"
|
class="progress w-full progress-bar"
|
||||||
:value="score"
|
:value="score"
|
||||||
|
|||||||
@@ -29,6 +29,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
|
<footer v-if="status" class="text-center w-full bottom-0 pb-4 bg-base-300 text-secondary-content">
|
||||||
|
<p class="text-center text-sm">
|
||||||
|
{{ $t("global.version", { version: status.build.version }) }} ~
|
||||||
|
{{ $t("global.build", { build: status.build.commit }) }}
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Sidebar -->
|
<!-- Sidebar -->
|
||||||
@@ -39,7 +45,7 @@
|
|||||||
<div class="w-60 py-5 md:py-10 bg-base-200 flex flex-grow-1 flex-col">
|
<div class="w-60 py-5 md:py-10 bg-base-200 flex flex-grow-1 flex-col">
|
||||||
<div class="space-y-8">
|
<div class="space-y-8">
|
||||||
<div class="flex flex-col items-center gap-4">
|
<div class="flex flex-col items-center gap-4">
|
||||||
<p>Welcome, {{ username }}</p>
|
<p>{{ $t("global.welcome", { username: username }) }}</p>
|
||||||
<NuxtLink class="avatar placeholder" to="/home">
|
<NuxtLink class="avatar placeholder" to="/home">
|
||||||
<div class="bg-base-300 text-neutral-content rounded-full w-24 p-4">
|
<div class="bg-base-300 text-neutral-content rounded-full w-24 p-4">
|
||||||
<AppLogo />
|
<AppLogo />
|
||||||
@@ -53,7 +59,7 @@
|
|||||||
<span>
|
<span>
|
||||||
<MdiPlus class="mr-1 -ml-1" />
|
<MdiPlus class="mr-1 -ml-1" />
|
||||||
</span>
|
</span>
|
||||||
Create
|
{{ $t("global.create") }}
|
||||||
</label>
|
</label>
|
||||||
<ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-40">
|
<ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-40">
|
||||||
<li v-for="btn in dropdown" :key="btn.name">
|
<li v-for="btn in dropdown" :key="btn.name">
|
||||||
@@ -83,7 +89,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Bottom -->
|
<!-- Bottom -->
|
||||||
<button class="mt-auto mx-2 hover:bg-base-300 p-3 rounded-btn" @click="logout">Sign Out</button>
|
<button class="mt-auto mx-2 hover:bg-base-300 p-3 rounded-btn" @click="logout">
|
||||||
|
{{ $t("global.sign_out") }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -101,12 +109,17 @@
|
|||||||
import MdiMagnify from "~icons/mdi/magnify";
|
import MdiMagnify from "~icons/mdi/magnify";
|
||||||
import MdiAccount from "~icons/mdi/account";
|
import MdiAccount from "~icons/mdi/account";
|
||||||
import MdiCog from "~icons/mdi/cog";
|
import MdiCog from "~icons/mdi/cog";
|
||||||
|
|
||||||
const username = computed(() => authCtx.user?.name || "User");
|
const username = computed(() => authCtx.user?.name || "User");
|
||||||
|
|
||||||
|
const pubApi = usePublicApi();
|
||||||
|
const { data: status } = useAsyncData(async () => {
|
||||||
|
const { data } = await pubApi.status();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
});
|
||||||
|
|
||||||
// Preload currency format
|
// Preload currency format
|
||||||
useFormatCurrency();
|
useFormatCurrency();
|
||||||
|
|
||||||
const modals = reactive({
|
const modals = reactive({
|
||||||
item: false,
|
item: false,
|
||||||
location: false,
|
location: false,
|
||||||
|
|||||||
127
frontend/locales/de.json
Normal file
127
frontend/locales/de.json
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
{
|
||||||
|
"components": {
|
||||||
|
"app": {
|
||||||
|
"import_dialog": {
|
||||||
|
"change_warning": "Das Verhalten beim Importieren vorhandener import_refs hat sich geändert. Wenn ein import_ref in der CSV-Datei vorhanden ist, wird der Gegenstand mit den Werten in der CSV-Datei aktualisiert.",
|
||||||
|
"description": "Importiere eine CSV-Datei, die deine Gegenstände, Etiketten und Standorte enthält. Siehe Dokumentation für weitere Informationen zum \nerforderlichen Format.",
|
||||||
|
"title": "Importiere CSV-Datei",
|
||||||
|
"upload": "Hochladen"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"global": {
|
||||||
|
"page_qr_code": {
|
||||||
|
"page_url": "Seiten-URL"
|
||||||
|
},
|
||||||
|
"password_score": {
|
||||||
|
"password_strength": "Passwortstärke"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"item": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Erstelle Gegenstand"
|
||||||
|
},
|
||||||
|
"view": {
|
||||||
|
"selectable": {
|
||||||
|
"card": "Karte",
|
||||||
|
"items": "Gegenstände",
|
||||||
|
"no_items": "Keine Gegenstände anzuzeigen",
|
||||||
|
"table": "Tabelle"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Erstelle Etikette"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Erstelle Standort"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"global": {
|
||||||
|
"build": "Build: { build }",
|
||||||
|
"confirm": "Bestätigen",
|
||||||
|
"create": "Erstellen",
|
||||||
|
"create_and_add": "Erstellen und weiteren hinzufügen",
|
||||||
|
"created": "Erstellt",
|
||||||
|
"email": "E-Mail",
|
||||||
|
"follow_dev": "Dem Entwickler folgen",
|
||||||
|
"github": "GitHub-Projekt",
|
||||||
|
"items": "Gegenstände",
|
||||||
|
"join_discord": "Discord beitreten",
|
||||||
|
"labels": "Etiketten",
|
||||||
|
"locations": "Standorte",
|
||||||
|
"name": "Name",
|
||||||
|
"password": "Passwort",
|
||||||
|
"read_docs": "Dokumentation lesen",
|
||||||
|
"search": "Suchen",
|
||||||
|
"sign_out": "Abmelden",
|
||||||
|
"submit": "Einreichen",
|
||||||
|
"version": "Version: { version }",
|
||||||
|
"welcome": "Willkommen, { username }"
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"disabled_registration": "Registrierung deaktiviert",
|
||||||
|
"dont_join_group": "Möchtest du nicht einer Gruppe beitreten?",
|
||||||
|
"joining_group": "Du trittst einer bereits bestehenden Gruppe bei!",
|
||||||
|
"login": "Anmelden",
|
||||||
|
"register": "Registrieren",
|
||||||
|
"remember_me": "Angemeldet bleiben",
|
||||||
|
"set_email": "Was ist deine E-Mail?",
|
||||||
|
"set_name": "Wie heißt du?",
|
||||||
|
"set_password": "Setze dein Passwort",
|
||||||
|
"tagline": "Verfolgen, Organisieren und Verwalten deiner Sachen."
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"add": "Hinzufügen",
|
||||||
|
"created_at": "Erstellt am",
|
||||||
|
"custom_fields": "Benutzerdefinierte Felder",
|
||||||
|
"field_selector": "Feldauswahl",
|
||||||
|
"field_value": "Feldwert",
|
||||||
|
"first": "Erste",
|
||||||
|
"include_archive": "Archivierte Elemente einbeziehen",
|
||||||
|
"last": "Letzte",
|
||||||
|
"negate_labels": "Ausgewählte Etiketten negieren",
|
||||||
|
"next_page": "Nächste Seite",
|
||||||
|
"no_results": "Keine Elemente gefunden",
|
||||||
|
"options": "Optionen",
|
||||||
|
"order_by": "Sortieren nach",
|
||||||
|
"pages": "Seite { page } von { totalPages }",
|
||||||
|
"prev_page": "Vorherige Seite",
|
||||||
|
"query_id": "Abfrage Asset-ID-Nummer: { id }",
|
||||||
|
"reset_search": "Suche zurücksetzen",
|
||||||
|
"results": "{ total } Ergebnisse",
|
||||||
|
"tip_1": "Standort- und Etikettenfilter verwenden die 'ODER'-Operation. Wenn mehr als eines ausgewählt ist, wird\n nur eines für eine Übereinstimmung benötigt.",
|
||||||
|
"tip_2": "Suchen, die mit '#' beginnen, fragen nach einer Asset-ID (Beispiel '#000-001')",
|
||||||
|
"tip_3": "Feldfilter verwenden die 'ODER'-Operation. Wenn mehr als eines ausgewählt ist, wird nur eines\n für eine Übereinstimmung benötigt.",
|
||||||
|
"tips": "Tipps",
|
||||||
|
"tips_sub": "Suchtipps",
|
||||||
|
"updated_at": "Aktualisiert am"
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"active": "Aktiv",
|
||||||
|
"change_password": "Passwort ändern",
|
||||||
|
"currency_format": "Währungsformat",
|
||||||
|
"current_password": "Aktuelles Passwort",
|
||||||
|
"delete_account": "Konto löschen",
|
||||||
|
"delete_account_sub": "Löschen Sie Ihr Konto und alle zugehörigen Daten. Dies kann nicht rückgängig gemacht werden.",
|
||||||
|
"enabled": "Aktiviert",
|
||||||
|
"gen_invite": "Einladungslink generieren",
|
||||||
|
"group_settings": "Gruppeneinstellungen",
|
||||||
|
"group_settings_sub": "Geteilte Gruppeneinstellungen. Möglicherweise müssen Sie Ihren Browser aktualisieren, damit einige Einstellungen wirksam werden.",
|
||||||
|
"inactive": "Inaktiv",
|
||||||
|
"new_password": "Neues Passwort",
|
||||||
|
"notifier_modal": "{ type, select, true {Bearbeiten} false {Erstellen} other {Andere}} Melder",
|
||||||
|
"notifiers": "Melder",
|
||||||
|
"notifiers_sub": "Erhalten Sie Benachrichtigungen für bevorstehende Wartungserinnerungen",
|
||||||
|
"test": "Test",
|
||||||
|
"theme_settings": "Themeneinstellungen",
|
||||||
|
"theme_settings_sub": "Themeneinstellungen werden im lokalen Speicher Ihres Browsers gespeichert. Sie können das Thema jederzeit ändern. Wenn Sie Probleme haben, Ihr Thema einzustellen, versuchen Sie, Ihren Browser zu aktualisieren.",
|
||||||
|
"update_group": "Gruppe aktualisieren",
|
||||||
|
"url": "URL",
|
||||||
|
"user_profile": "Benutzerprofil",
|
||||||
|
"user_profile_sub": "Benutzer einladen und Ihr Konto verwalten."
|
||||||
|
}
|
||||||
|
}
|
||||||
128
frontend/locales/en.json
Normal file
128
frontend/locales/en.json
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
{
|
||||||
|
"components": {
|
||||||
|
"app": {
|
||||||
|
"import_dialog": {
|
||||||
|
"change_warning": "Behavior for imports with existing import_refs has changed. If an import_ref is present in the CSV file, the \nitem will be updated with the values in the CSV file.",
|
||||||
|
"description": "Import a CSV file containing your items, labels, and locations. See documentation for more information on the \nrequired format.",
|
||||||
|
"title": "Import CSV File",
|
||||||
|
"upload": "Upload"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"global": {
|
||||||
|
"page_qr_code": {
|
||||||
|
"page_url": "Page URL"
|
||||||
|
},
|
||||||
|
"password_score": {
|
||||||
|
"password_strength": "Password Strength"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"item": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Create Item",
|
||||||
|
"photo_button": "Photo \uD83D\uDCF7"
|
||||||
|
},
|
||||||
|
"view": {
|
||||||
|
"selectable": {
|
||||||
|
"card": "Card",
|
||||||
|
"items": "Items",
|
||||||
|
"no_items": "No Items to Display",
|
||||||
|
"table": "Table"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Create Label"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Create Location"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"global": {
|
||||||
|
"build": "Build: { build }",
|
||||||
|
"confirm": "Confirm",
|
||||||
|
"create": "Create",
|
||||||
|
"create_and_add": "Create and Add Another",
|
||||||
|
"created": "Created",
|
||||||
|
"email": "Email",
|
||||||
|
"follow_dev": "Follow the Developer",
|
||||||
|
"github": "GitHub Project",
|
||||||
|
"items": "Items",
|
||||||
|
"join_discord": "Join the Discord",
|
||||||
|
"labels": "Labels",
|
||||||
|
"locations": "Locations",
|
||||||
|
"name": "Name",
|
||||||
|
"password": "Password",
|
||||||
|
"read_docs": "Read the Docs",
|
||||||
|
"search": "Search",
|
||||||
|
"sign_out": "Sign Out",
|
||||||
|
"submit": "Submit",
|
||||||
|
"version": "Version: { version }",
|
||||||
|
"welcome": "Welcome, { username }"
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"disabled_registration": "Registration Disabled",
|
||||||
|
"dont_join_group": "Don't want to join a group?",
|
||||||
|
"joining_group": "You're Joining an Existing Group!",
|
||||||
|
"login": "Login",
|
||||||
|
"register": "Register",
|
||||||
|
"remember_me": "Remember Me",
|
||||||
|
"set_email": "What's your email?",
|
||||||
|
"set_name": "What's your name?",
|
||||||
|
"set_password": "Set your password",
|
||||||
|
"tagline": "Track, Organize, and Manage your Things."
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"add": "Add",
|
||||||
|
"created_at": "Created At",
|
||||||
|
"custom_fields": "Custom Fields",
|
||||||
|
"field_selector": "Field Selector",
|
||||||
|
"field_value": "Field Value",
|
||||||
|
"first": "First",
|
||||||
|
"include_archive": "Include Archived Items",
|
||||||
|
"last": "Last",
|
||||||
|
"negate_labels": "Negate Selected Labels",
|
||||||
|
"next_page": "Next Page",
|
||||||
|
"no_results": "No Items Found",
|
||||||
|
"options": "Options",
|
||||||
|
"order_by": "Order By",
|
||||||
|
"pages": "Page { page } of { totalPages }",
|
||||||
|
"prev_page": "Previous Page",
|
||||||
|
"query_id": "Querying Asset ID Number: { id }",
|
||||||
|
"reset_search": "Reset Search",
|
||||||
|
"results": "{ total } Results",
|
||||||
|
"tip_1": "Location and label filters use the 'OR' operation. If more than one is selected only one will be\n required for a match.",
|
||||||
|
"tip_2": "Searches prefixed with '#'' will query for a asset ID (example '#000-001')",
|
||||||
|
"tip_3": "Field filters use the 'OR' operation. If more than one is selected only one will be required for a\n match.",
|
||||||
|
"tips": "Tips",
|
||||||
|
"tips_sub": "Search Tips",
|
||||||
|
"updated_at": "Updated At"
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"active": "Active",
|
||||||
|
"change_password": "Change Password",
|
||||||
|
"currency_format": "Currency Format",
|
||||||
|
"current_password": "Current Password",
|
||||||
|
"delete_account": "Delete Account",
|
||||||
|
"delete_account_sub": "Delete your account and all its associated data. This can not be undone.",
|
||||||
|
"enabled": "Enabled",
|
||||||
|
"gen_invite": "Generate Invite Link",
|
||||||
|
"group_settings": "Group Settings",
|
||||||
|
"group_settings_sub": "Shared Group Settings. You may need to refresh your browser for some settings to apply.",
|
||||||
|
"inactive": "Inactive",
|
||||||
|
"new_password": "New Password",
|
||||||
|
"notifier_modal": "{ type, select, true {Edit} false {Create} other {Other}} Notifier",
|
||||||
|
"notifiers": "Notifiers",
|
||||||
|
"notifiers_sub": "Get notifications for upcoming maintenance reminders",
|
||||||
|
"test": "Test",
|
||||||
|
"theme_settings": "Theme Settings",
|
||||||
|
"theme_settings_sub": "Theme settings are stored in your browser's local storage. You can change the theme at any time. If you're\n having trouble setting your theme try refreshing your browser.",
|
||||||
|
"update_group": "Update Group",
|
||||||
|
"url": "URL",
|
||||||
|
"user_profile": "User Profile",
|
||||||
|
"user_profile_sub": "Invite users, and manage your account."
|
||||||
|
}
|
||||||
|
}
|
||||||
127
frontend/locales/es.json
Normal file
127
frontend/locales/es.json
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
{
|
||||||
|
"components": {
|
||||||
|
"app": {
|
||||||
|
"import_dialog": {
|
||||||
|
"change_warning": "Se ha modificado el comportamiento de las importaciones con import_refs existentes. Si existe una import_ref en el archivo CSV, el \nelemento se actualizará con los valores del archivo CSV.",
|
||||||
|
"description": "Importa un archivo CSV que contenga tus elementos, etiquetas y ubicaciones. Consulta la documentación para obtener más información sobre el \nformato requerido.",
|
||||||
|
"title": "Importar Archivo CSV",
|
||||||
|
"upload": "Subir"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"global": {
|
||||||
|
"page_qr_code": {
|
||||||
|
"page_url": "URL de página"
|
||||||
|
},
|
||||||
|
"password_score": {
|
||||||
|
"password_strength": "Seguridad de la contraseña"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"item": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Crear Elemento"
|
||||||
|
},
|
||||||
|
"view": {
|
||||||
|
"selectable": {
|
||||||
|
"card": "Tarjeta",
|
||||||
|
"items": "Elementos",
|
||||||
|
"no_items": "No hay elementos para mostrar",
|
||||||
|
"table": "Tabla"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Crear Etiqueta"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Crear Ubicación"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"global": {
|
||||||
|
"build": "Compilación: { build }",
|
||||||
|
"confirm": "Confirmar",
|
||||||
|
"create": "Crear",
|
||||||
|
"created": "Creado",
|
||||||
|
"email": "Email",
|
||||||
|
"github": "Proyecto GitHub",
|
||||||
|
"items": "Elementos",
|
||||||
|
"join_discord": "Únete al Discord",
|
||||||
|
"labels": "Etiquetas",
|
||||||
|
"locations": "Ubicaciones",
|
||||||
|
"name": "Nombre",
|
||||||
|
"password": "Contraseña",
|
||||||
|
"read_docs": "Lee la Documentación",
|
||||||
|
"search": "Buscar",
|
||||||
|
"sign_out": "Cerrar Sesión",
|
||||||
|
"submit": "Enviar",
|
||||||
|
"welcome": "Bienvenido/a, { username }",
|
||||||
|
"create_and_add": "Crear y Añadir Otro",
|
||||||
|
"follow_dev": "Seguir al Desarrollador",
|
||||||
|
"version": "Versión: { version }"
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"disabled_registration": "Registro Desactivado",
|
||||||
|
"dont_join_group": "¿No quieres unirte a un grupo?",
|
||||||
|
"login": "Iniciar sesión",
|
||||||
|
"register": "Registrarse",
|
||||||
|
"remember_me": "Recuérdame",
|
||||||
|
"set_email": "¿Cuál es tu email?",
|
||||||
|
"set_name": "¿Cómo te llamas?",
|
||||||
|
"set_password": "Establece tu contraseña",
|
||||||
|
"tagline": "Rastrea, Organiza y Gestiona tus Cosas.",
|
||||||
|
"joining_group": "¡Te estás uniendo a un grupo existente!"
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"add": "Añadir",
|
||||||
|
"created_at": "Creado El",
|
||||||
|
"custom_fields": "Campos Personalizados",
|
||||||
|
"field_selector": "Selector de Campo",
|
||||||
|
"field_value": "Valor del Campo",
|
||||||
|
"first": "Primer",
|
||||||
|
"include_archive": "Incluir Elementos Archivados",
|
||||||
|
"last": "Último",
|
||||||
|
"negate_labels": "Negar Etiquetas Seleccionadas",
|
||||||
|
"next_page": "Siguiente Página",
|
||||||
|
"no_results": "No se Encontraron Elementos",
|
||||||
|
"options": "Opciones",
|
||||||
|
"order_by": "Ordenar Por",
|
||||||
|
"pages": "Página { page } de { totalPages }",
|
||||||
|
"prev_page": "Anterior Página",
|
||||||
|
"query_id": "Consultar Número ID del Activo: { id }",
|
||||||
|
"reset_search": "Restablecer Búsqueda",
|
||||||
|
"results": "{ total } Resultados",
|
||||||
|
"tip_2": "Las búsquedas precedidas de \"#\" buscarán un ID de activo (por ejemplo, \"#000-001\")",
|
||||||
|
"tip_3": "Los filtros de campo utilizan el operador \"OR\". Si se selecciona más de uno, sólo se requerirá uno para una\n coincidencia.",
|
||||||
|
"tip_1": "Los filtros de ubicación y etiquetas utilizan el operador \"OR\". Si se selecciona más de uno, sólo uno será\n necesario para obtener una coincidencia.",
|
||||||
|
"tips": "Sugerencias",
|
||||||
|
"tips_sub": "Sugerencias de Búsqueda",
|
||||||
|
"updated_at": "Actualizado El"
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"active": "Activo",
|
||||||
|
"change_password": "Cambiar Contraseña",
|
||||||
|
"currency_format": "Formato Divisa",
|
||||||
|
"current_password": "Contraseña Actual",
|
||||||
|
"delete_account": "Eliminar Cuenta",
|
||||||
|
"enabled": "Habilitado",
|
||||||
|
"gen_invite": "Generar Enlace de Invitación",
|
||||||
|
"group_settings": "Ajustes de Grupo",
|
||||||
|
"group_settings_sub": "Configuración de Grupo Compartido. Es posible que tengas que actualizar tu navegador para que se apliquen algunos ajustes.",
|
||||||
|
"inactive": "Inactivo",
|
||||||
|
"new_password": "Nueva Contraseña",
|
||||||
|
"notifiers": "Notificaciones",
|
||||||
|
"notifiers_sub": "Recibe notificaciones de los próximos recordatorios de mantenimiento",
|
||||||
|
"test": "Probar",
|
||||||
|
"theme_settings": "Ajustes de Tema",
|
||||||
|
"update_group": "Actualizar Grupo",
|
||||||
|
"url": "URL",
|
||||||
|
"user_profile": "Perfil de Usuario",
|
||||||
|
"user_profile_sub": "Invita a usuarios y gestiona tu cuenta.",
|
||||||
|
"delete_account_sub": "Elimina tu cuenta y todos sus datos asociados. Esto no se puede deshacer.",
|
||||||
|
"notifier_modal": "{ type, select, true {Edit} false {Create} other {Other}} Notificación",
|
||||||
|
"theme_settings_sub": "La configuración del tema se guarda en el almacenamiento local de tu navegador. Puedes cambiar el tema en cualquier momento. Si tienes\n problemas para configurar el tema, prueba a actualizar el navegador."
|
||||||
|
}
|
||||||
|
}
|
||||||
128
frontend/locales/fr.json
Normal file
128
frontend/locales/fr.json
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
{
|
||||||
|
"global": {
|
||||||
|
"email": "Courriel",
|
||||||
|
"read_docs": "Lire la documentation",
|
||||||
|
"password": "Mot de passe",
|
||||||
|
"github": "Projet GitHub",
|
||||||
|
"join_discord": "Rejoindre le Discord",
|
||||||
|
"follow_dev": "Suivre le développeur",
|
||||||
|
"version": "Version : { version }",
|
||||||
|
"build": "Assemblage : { build }",
|
||||||
|
"create": "Créer",
|
||||||
|
"submit": "Soumettre",
|
||||||
|
"create_and_add": "Créer et en ajouter un autre",
|
||||||
|
"confirm": "Confirmer",
|
||||||
|
"sign_out": "Déconnexion",
|
||||||
|
"welcome": "Bienvenue, { username }",
|
||||||
|
"created": "Créé",
|
||||||
|
"labels": "Étiquettes",
|
||||||
|
"locations": "Emplacements",
|
||||||
|
"name": "Nom",
|
||||||
|
"search": "Rechercher",
|
||||||
|
"items": "Articles"
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"set_email": "Quel est vôtre courriel ?",
|
||||||
|
"set_name": "Quel est votre nom ?",
|
||||||
|
"login": "Se connecter",
|
||||||
|
"register": "S'enregistrer",
|
||||||
|
"remember_me": "Se souvenir de moi",
|
||||||
|
"set_password": "Définir votre mot de passe",
|
||||||
|
"dont_join_group": "Vous ne voulez pas joindre un groupe ?",
|
||||||
|
"tagline": "Répertoriez, organisez et gérez vos affaires.",
|
||||||
|
"disabled_registration": "Les inscriptions sont désactivées",
|
||||||
|
"joining_group": "Vous rejoignez un groupe existant !"
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"label": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Créer une étiquette"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"item": {
|
||||||
|
"view": {
|
||||||
|
"selectable": {
|
||||||
|
"items": "Articles",
|
||||||
|
"no_items": "Nb. d’articles à afficher",
|
||||||
|
"table": "Tableau",
|
||||||
|
"card": "Carte"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Créer un article",
|
||||||
|
"photo_button": "Photo 📷"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Créer un emplacement"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"global": {
|
||||||
|
"password_score": {
|
||||||
|
"password_strength": "Solidité du mot de passe"
|
||||||
|
},
|
||||||
|
"page_qr_code": {
|
||||||
|
"page_url": "URL de la page"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"app": {
|
||||||
|
"import_dialog": {
|
||||||
|
"title": "Importer un fichier CSV",
|
||||||
|
"upload": "Téléverser",
|
||||||
|
"description": "Importer un fichier CSV contenant vos articles, étiquettes, et emplacements. Voir la documentation pour plus d’informations sur le format requis.",
|
||||||
|
"change_warning": "Le comportement lors d’importations avec des import_ref existants a changé. Si une valeur pour import_ref est présente dans le fichier CSV, alors l’élément sera mis à jour avec celle-ci."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"notifiers_sub": "Recevez des notifications pour vous prévenir des prochaines maintenances.",
|
||||||
|
"active": "Actif",
|
||||||
|
"enabled": "Activé",
|
||||||
|
"test": "Test",
|
||||||
|
"current_password": "Mot de passe actuel",
|
||||||
|
"new_password": "Nouveau mot de passe",
|
||||||
|
"change_password": "Changer de mot de passe",
|
||||||
|
"inactive": "Inactif",
|
||||||
|
"notifiers": "Notifications",
|
||||||
|
"gen_invite": "Générer un lien d’invitation",
|
||||||
|
"user_profile": "Profil utilisateur",
|
||||||
|
"user_profile_sub": "Gérez votre compte et invitez des utilisateurs.",
|
||||||
|
"url": "URL",
|
||||||
|
"delete_account": "Effacer le compte",
|
||||||
|
"delete_account_sub": "Supprimer le compte et toutes ses données. Aucune récupération possible.",
|
||||||
|
"group_settings": "Paramètres du groupe",
|
||||||
|
"group_settings_sub": "Paramètres du groupe partagé. Il peut être nécessaire de recharger la page pour qu’ils deviennent effectifs.",
|
||||||
|
"currency_format": "Format de la devise",
|
||||||
|
"update_group": "Mettre à jour le groupe",
|
||||||
|
"theme_settings": "Paramètres du thème",
|
||||||
|
"theme_settings_sub": "Les paramètres du thème sont stockés dans le navigateur. Vous pouvez les changer à tout moment. Si vous\nrencontrez des problèmes, il est conseillé de rafraichir la page.",
|
||||||
|
"notifier_modal": ""
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"add": "Ajouter",
|
||||||
|
"created_at": "",
|
||||||
|
"custom_fields": "Champs personnalisés",
|
||||||
|
"field_selector": "Sélecteur de champ",
|
||||||
|
"field_value": "Valeur du champ",
|
||||||
|
"first": "Premier",
|
||||||
|
"include_archive": "Inclure les éléments archivés",
|
||||||
|
"last": "Dernier",
|
||||||
|
"negate_labels": "Négliger les étiquettes sélectionnées",
|
||||||
|
"next_page": "Page suivante",
|
||||||
|
"no_results": "Aucun élément trouvé",
|
||||||
|
"options": "Options",
|
||||||
|
"order_by": "Trier par",
|
||||||
|
"pages": "Page { page } sur { totalPages }",
|
||||||
|
"prev_page": "Page précédente",
|
||||||
|
"query_id": "",
|
||||||
|
"reset_search": "Réinitialiser la recherche",
|
||||||
|
"tip_1": "Les filtres d’emplacement et d’étiquette utilisent l’opérateur « OU ».\nUn seul des filtres n’a besoin de correspondre pour retourner un résultat.",
|
||||||
|
"tip_2": "",
|
||||||
|
"tip_3": "Les filtres de champ utilisent l’opérateur « OU ».\nUn seul des filtres n’a besoin de correspondre pour retourner un résultat.",
|
||||||
|
"tips": "Conseils",
|
||||||
|
"tips_sub": "Conseils pour la recherche",
|
||||||
|
"updated_at": "",
|
||||||
|
"results": "{ total } résultats"
|
||||||
|
}
|
||||||
|
}
|
||||||
127
frontend/locales/it.json
Normal file
127
frontend/locales/it.json
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
{
|
||||||
|
"components": {
|
||||||
|
"app": {
|
||||||
|
"import_dialog": {
|
||||||
|
"change_warning": "Il comportamento per le importazioni con import_ref esistenti è cambiato. Se un import_ref è presente nel file CSV,\n l'elemento verrà aggiornato con i valori presenti nel file CSV.",
|
||||||
|
"description": "Importa un file CSV contenente gli oggetti, le etichette e le posizioni. Vedi la documentazione per ulteriori informazioni sul \nformato richiesto.",
|
||||||
|
"title": "Importa File CSV",
|
||||||
|
"upload": "Carica"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"global": {
|
||||||
|
"page_qr_code": {
|
||||||
|
"page_url": "URL della Pagina"
|
||||||
|
},
|
||||||
|
"password_score": {
|
||||||
|
"password_strength": "Complessità della Password"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"item": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Crea Oggetto"
|
||||||
|
},
|
||||||
|
"view": {
|
||||||
|
"selectable": {
|
||||||
|
"card": "Scheda",
|
||||||
|
"items": "Oggetti",
|
||||||
|
"no_items": "Nessun Oggetto da Visualizzare",
|
||||||
|
"table": "Tabella"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Crea Etichetta"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Crea Posizione"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"global": {
|
||||||
|
"build": "Build: { build }",
|
||||||
|
"confirm": "Conferma",
|
||||||
|
"create": "Crea",
|
||||||
|
"create_and_add": "Crea e aggiungi un altro",
|
||||||
|
"created": "Creato",
|
||||||
|
"email": "Email",
|
||||||
|
"follow_dev": "Segui lo Sviluppatore",
|
||||||
|
"github": "Progetto GitHub",
|
||||||
|
"items": "Articoli",
|
||||||
|
"join_discord": "Unisciti a Discord",
|
||||||
|
"labels": "Etichette",
|
||||||
|
"locations": "Posizioni",
|
||||||
|
"name": "Nome",
|
||||||
|
"password": "Password",
|
||||||
|
"read_docs": "Leggi la Documentazione",
|
||||||
|
"search": "Cerca",
|
||||||
|
"sign_out": "Disconnetti",
|
||||||
|
"submit": "Invia",
|
||||||
|
"version": "Versione: { version }",
|
||||||
|
"welcome": "Benvenuto, { username }"
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"disabled_registration": "Registrazione Disabilitata",
|
||||||
|
"dont_join_group": "Non vuoi unirti a un gruppo?",
|
||||||
|
"joining_group": "Stai unendoti a un gruppo esistente!",
|
||||||
|
"login": "Accedi",
|
||||||
|
"register": "Registrati",
|
||||||
|
"remember_me": "Ricordami",
|
||||||
|
"set_email": "Qual è la tua email?",
|
||||||
|
"set_name": "Come ti chiami?",
|
||||||
|
"set_password": "Imposta la tua password",
|
||||||
|
"tagline": "Tieni traccia, Organizza e Gestisci le tue Cose."
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"add": "Aggiungi",
|
||||||
|
"created_at": "Creato Il",
|
||||||
|
"custom_fields": "Campi Personalizzati",
|
||||||
|
"field_selector": "Selettore di Campo",
|
||||||
|
"field_value": "Valore del Campo",
|
||||||
|
"first": "Primo",
|
||||||
|
"include_archive": "Includi Articoli Archiviati",
|
||||||
|
"last": "Ultimo",
|
||||||
|
"negate_labels": "Negare Etichette Selezionate",
|
||||||
|
"next_page": "Pagina Successiva",
|
||||||
|
"no_results": "Nessun Articolo Trovato",
|
||||||
|
"options": "Opzioni",
|
||||||
|
"order_by": "Ordina Per",
|
||||||
|
"pages": "Pagina { page } di { totalPages }",
|
||||||
|
"prev_page": "Pagina Precedente",
|
||||||
|
"query_id": "ID dell'Asset in Ricerca: { id }",
|
||||||
|
"reset_search": "Reimposta Ricerca",
|
||||||
|
"results": "{ total } Risultati",
|
||||||
|
"tip_1": "I filtri di posizione ed etichetta utilizzano l'operazione 'OR'. Se ne viene selezionato più\n di uno, ne sarà richiesto solo uno per una corrispondenza.",
|
||||||
|
"tip_2": "Le ricerche con prefisso '#' cercheranno un ID asset (esempio '#000-001')",
|
||||||
|
"tip_3": "I filtri di campo utilizzano l'operazione 'OR'. Se ne viene selezionato più di uno, ne sarà\n richiesto solo uno per una corrispondenza.",
|
||||||
|
"tips": "Suggerimenti",
|
||||||
|
"tips_sub": "Suggerimenti per la Ricerca",
|
||||||
|
"updated_at": "Aggiornato Il"
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"active": "Attivo",
|
||||||
|
"change_password": "Cambia Password",
|
||||||
|
"currency_format": "Formato Valuta",
|
||||||
|
"current_password": "Password Corrente",
|
||||||
|
"delete_account": "Elimina Account",
|
||||||
|
"delete_account_sub": "Elimina il tuo account e tutti i dati associati. Questa operazione non può essere annullata.",
|
||||||
|
"enabled": "Abilitato",
|
||||||
|
"gen_invite": "Genera Link di Invito",
|
||||||
|
"group_settings": "Impostazioni Gruppo",
|
||||||
|
"group_settings_sub": "Impostazioni Gruppo Condivise. Potrebbe essere necessario aggiornare il browser affinché alcune impostazioni vengano applicate.",
|
||||||
|
"inactive": "Inattivo",
|
||||||
|
"new_password": "Nuova Password",
|
||||||
|
"notifier_modal": "{ type, select, true {Modifica} false {Crea} other {Altro}} Notifier",
|
||||||
|
"notifiers": "Notifiche",
|
||||||
|
"notifiers_sub": "Ricevi notifiche per i prossimi promemoria di manutenzione",
|
||||||
|
"test": "Test",
|
||||||
|
"theme_settings": "Impostazioni Tema",
|
||||||
|
"theme_settings_sub": "Le impostazioni del tema sono memorizzate nella memoria locale del tuo browser. Puoi cambiare il tema \nin qualsiasi momento. Se hai problemi a impostare il tuo tema, prova a ricaricare la pagina.",
|
||||||
|
"update_group": "Aggiorna Gruppo",
|
||||||
|
"url": "URL",
|
||||||
|
"user_profile": "Profilo Utente",
|
||||||
|
"user_profile_sub": "Invita utenti e gestisci il tuo account."
|
||||||
|
}
|
||||||
|
}
|
||||||
128
frontend/locales/nl.json
Normal file
128
frontend/locales/nl.json
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
{
|
||||||
|
"global": {
|
||||||
|
"version": "Versie: { version }",
|
||||||
|
"github": "GitHub Project",
|
||||||
|
"join_discord": "Sluit je aan bij de Discord",
|
||||||
|
"follow_dev": "Volg de ontwikkelaar",
|
||||||
|
"read_docs": "Lees de documentatie",
|
||||||
|
"email": "E-mail",
|
||||||
|
"submit": "Indienen",
|
||||||
|
"confirm": "Bevestigen",
|
||||||
|
"create": "Maken",
|
||||||
|
"create_and_add": "Maak en voeg nog een toe",
|
||||||
|
"password": "Wachtwoord",
|
||||||
|
"build": "Bouw: { build }",
|
||||||
|
"created": "Gemaakt",
|
||||||
|
"welcome": "Welkom, { username }",
|
||||||
|
"sign_out": "Log uit",
|
||||||
|
"labels": "etiketten",
|
||||||
|
"locations": "Locaties",
|
||||||
|
"name": "Naam",
|
||||||
|
"items": "artikelen",
|
||||||
|
"search": "Zoeken"
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"disabled_registration": "Registratie uitgeschakeld",
|
||||||
|
"login": "Log in",
|
||||||
|
"register": "Registreer",
|
||||||
|
"remember_me": "Onthoud mij",
|
||||||
|
"set_email": "Wat is je mailadres?",
|
||||||
|
"set_password": "Stel je wachtwoord in",
|
||||||
|
"set_name": "Wat is je naam?",
|
||||||
|
"joining_group": "Je neemt deel aan een bestaande groep!",
|
||||||
|
"tagline": "Volg, Organiseer en beheer je dingen.",
|
||||||
|
"dont_join_group": "Wil je niet aan een groep deelnemen?"
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"global": {
|
||||||
|
"password_score": {
|
||||||
|
"password_strength": "Wachtwoord sterkte"
|
||||||
|
},
|
||||||
|
"page_qr_code": {
|
||||||
|
"page_url": "Pagina URL"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"app": {
|
||||||
|
"import_dialog": {
|
||||||
|
"title": "Importeer CSV bestand",
|
||||||
|
"change_warning": "Gedrag voor importeren met bestaande import_refs is veranderd. Als een import_refs reeds bestaat in het CSV bestand, het\nobject zal worden aangepast met de waardes van het CSV bestand.",
|
||||||
|
"upload": "Upload",
|
||||||
|
"description": "Importeer een CSV bestand met je objecten, labels en locaties. Zie documentatie voor meer informatie m.b.t.\n vereist format."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"item": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Maak object",
|
||||||
|
"photo_button": "Foto 📷"
|
||||||
|
},
|
||||||
|
"view": {
|
||||||
|
"selectable": {
|
||||||
|
"items": "Objecten",
|
||||||
|
"card": "Kaart",
|
||||||
|
"table": "Tabel",
|
||||||
|
"no_items": "Geen objecten om te tonen"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Maak label"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Maak locatie"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"gen_invite": "Genereer Uitnodigingslink",
|
||||||
|
"notifier_modal": "{ type, select, true {Bewerk} false {Creëer} other {overig}} Notifier",
|
||||||
|
"change_password": "Verander Wachtwoord",
|
||||||
|
"current_password": "Huidig Wachtwoord",
|
||||||
|
"new_password": "Nieuw Wachtwoord",
|
||||||
|
"url": "URL",
|
||||||
|
"enabled": "ingeschakeld",
|
||||||
|
"test": "Test",
|
||||||
|
"user_profile": "Gebruikers Profiel",
|
||||||
|
"user_profile_sub": "Nodig gebruikers uit, en beheer je account.",
|
||||||
|
"active": "Actief",
|
||||||
|
"inactive": "Inactief",
|
||||||
|
"notifiers_sub": "Krijg notificaties voor opkomende onderhouds herinneringen",
|
||||||
|
"group_settings_sub": "Gedeelde groepsinstellingen",
|
||||||
|
"group_settings": "Groeps Instellingen",
|
||||||
|
"notifiers": "Notificatie",
|
||||||
|
"currency_format": "Valutanotatie",
|
||||||
|
"update_group": "Groep bijwerken",
|
||||||
|
"theme_settings": "Theme instellingen",
|
||||||
|
"theme_settings_sub": "",
|
||||||
|
"delete_account": "Verwijder account",
|
||||||
|
"delete_account_sub": "Verwijder je account en alle geassocieerde data. Deze actie kan niet ongedaan worden."
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"tip_1": "Locatie- en labelfilters gebruiken de 'OF' -werking. Als er meer dan een is geselecteerd,\nis er maar een nodig voor een overeenkomst.",
|
||||||
|
"tip_2": "Zoekopdrachten voorafgegaan door '#'' zullen om een object-ID vragen (bijvoorbeeld '#000-001')",
|
||||||
|
"tip_3": "",
|
||||||
|
"tips_sub": "Zoektips",
|
||||||
|
"updated_at": "Bijgewerkt op",
|
||||||
|
"pages": "Pagina { page } van { totalPages }",
|
||||||
|
"prev_page": "Vorige pagina",
|
||||||
|
"query_id": "ID-nummer van object opvragen: { id }",
|
||||||
|
"reset_search": "Reset Zoeken",
|
||||||
|
"tips": "Tips",
|
||||||
|
"no_results": "Geen Items Gevonden",
|
||||||
|
"options": "Opties",
|
||||||
|
"order_by": "Sorteren op",
|
||||||
|
"results": "{ total } Resultaten",
|
||||||
|
"add": "Toevoegen",
|
||||||
|
"created_at": "Aangemaakt op",
|
||||||
|
"custom_fields": "Aangepaste velden",
|
||||||
|
"field_selector": "Veld selectie",
|
||||||
|
"field_value": "Veldwaarde",
|
||||||
|
"first": "Eerst",
|
||||||
|
"include_archive": "Inclusief gearchiveerde items",
|
||||||
|
"last": "Laatste",
|
||||||
|
"negate_labels": "Negeer Geselecteerde Etiketten",
|
||||||
|
"next_page": "Volgende pagina"
|
||||||
|
}
|
||||||
|
}
|
||||||
128
frontend/locales/ru.json
Normal file
128
frontend/locales/ru.json
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
{
|
||||||
|
"components": {
|
||||||
|
"app": {
|
||||||
|
"import_dialog": {
|
||||||
|
"title": "Импорт CSV файла",
|
||||||
|
"change_warning": "Изменено поведение для импортов с существующими import_ref. Если в CSV-файле присутствует import_ref, \nто элемент будет обновлен значениями из CSV-файла.",
|
||||||
|
"description": "Импортируйте CSV-файл, содержащий ваши предметы, ярлыки и местоположения. Для получения информации о требуемом формате \nсм. документацию.",
|
||||||
|
"upload": "Загрузить"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"global": {
|
||||||
|
"page_qr_code": {
|
||||||
|
"page_url": "URL-адрес страницы"
|
||||||
|
},
|
||||||
|
"password_score": {
|
||||||
|
"password_strength": "Сложность пароля"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"item": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Создать элемент",
|
||||||
|
"photo_button": "Фото 📷"
|
||||||
|
},
|
||||||
|
"view": {
|
||||||
|
"selectable": {
|
||||||
|
"items": "Элементы",
|
||||||
|
"no_items": "Нет элементов для отображения",
|
||||||
|
"table": "Таблица",
|
||||||
|
"card": "Карта"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Создать локацию"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Создать ярлык"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"global": {
|
||||||
|
"email": "Email",
|
||||||
|
"items": "Элементы",
|
||||||
|
"build": "Сборка: { build }",
|
||||||
|
"confirm": "Подтвердить",
|
||||||
|
"create": "Создать",
|
||||||
|
"create_and_add": "Создать и добавить еще",
|
||||||
|
"created": "Создано",
|
||||||
|
"follow_dev": "Следить за разработчиком",
|
||||||
|
"github": "Проект Github",
|
||||||
|
"labels": "Ярлыки",
|
||||||
|
"join_discord": "Присоединяйтесь к Discord",
|
||||||
|
"locations": "Локации",
|
||||||
|
"name": "Имя",
|
||||||
|
"password": "Пароль",
|
||||||
|
"read_docs": "Прочитать документацию",
|
||||||
|
"search": "Поиск",
|
||||||
|
"sign_out": "Выйти",
|
||||||
|
"submit": "Отправить",
|
||||||
|
"version": "Версия: { version }",
|
||||||
|
"welcome": "Добро пожаловать, { username }"
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"login": "Войти",
|
||||||
|
"register": "Зарегистрироваться",
|
||||||
|
"set_email": "Какой у вас адрес электронной почты?",
|
||||||
|
"set_name": "Как вас зовут?",
|
||||||
|
"set_password": "Установите пароль",
|
||||||
|
"tagline": "Отслеживайте, упорядочивайте и управляйте своими вещами.",
|
||||||
|
"disabled_registration": "Регистрация отключена",
|
||||||
|
"dont_join_group": "Не хотите ли вступить в группу?",
|
||||||
|
"remember_me": "Запомнить меня",
|
||||||
|
"joining_group": "Вы присоединяетесь к уже существующей группе!"
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"add": "Добавить",
|
||||||
|
"created_at": "Создано в",
|
||||||
|
"custom_fields": "Настраиваемые поля",
|
||||||
|
"first": "Первый",
|
||||||
|
"pages": "Страница {page} из {totalPages}",
|
||||||
|
"prev_page": "Предыдущая страница",
|
||||||
|
"reset_search": "Сбросить Поиск",
|
||||||
|
"field_selector": "Поле выбора",
|
||||||
|
"field_value": "Значение поля",
|
||||||
|
"last": "Последний",
|
||||||
|
"negate_labels": "Снять выбранные ярлыки",
|
||||||
|
"next_page": "Следующая страница",
|
||||||
|
"no_results": "Элементы не найдены",
|
||||||
|
"options": "Параметры",
|
||||||
|
"results": "{ total } Результатов",
|
||||||
|
"tips": "Подсказки",
|
||||||
|
"tips_sub": "Поисковые подсказки",
|
||||||
|
"updated_at": "Обновлено в",
|
||||||
|
"tip_3": "Фильтры по полю используют операцию «ИЛИ». Если выбрано несколько фильтров, для совпадения\n требуется только один.",
|
||||||
|
"tip_2": "Поисковые запросы с префиксом \"#\" должны включать в себя ID актива (прим. '#000-001')",
|
||||||
|
"include_archive": "Включить архивированные элементы",
|
||||||
|
"order_by": "Сортировка по",
|
||||||
|
"query_id": "Запрос идентификационного номера актива: { id }",
|
||||||
|
"tip_1": "При фильтрации по локации и по ярлыкам используется логический оператор «ИЛИ». Если выбрано несколько фильтров, то для срабатывания\n требуется лишь одно совпадение."
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"new_password": "Новый пароль",
|
||||||
|
"update_group": "Обновить группу",
|
||||||
|
"active": "Активный",
|
||||||
|
"change_password": "Изменить пароль",
|
||||||
|
"currency_format": "Формат валюты",
|
||||||
|
"current_password": "Текущий пароль",
|
||||||
|
"delete_account": "Удалить аккаунт",
|
||||||
|
"group_settings": "Настройки группы",
|
||||||
|
"inactive": "Неактивный",
|
||||||
|
"notifier_modal": "{ type, select, true {Edit} false {Create} other {Other}} Уведомитель",
|
||||||
|
"notifiers": "Уведомители",
|
||||||
|
"notifiers_sub": "Получить уведомление о предстоящем обслуживании",
|
||||||
|
"test": "Тест",
|
||||||
|
"theme_settings": "Настройки темы",
|
||||||
|
"url": "URL",
|
||||||
|
"user_profile": "Профиль пользователя",
|
||||||
|
"user_profile_sub": "Приглашайте пользователей и управляйте своим аккаунтом.",
|
||||||
|
"enabled": "Активен",
|
||||||
|
"theme_settings_sub": "Настройки темы хранятся в локальном хранилище браузера. Вы можете изменить тему в любое время. Если у вас\n не удается установить тему, попробуйте перезапустить браузер.",
|
||||||
|
"delete_account_sub": "Удалить свой аккаунт и все связанные с ним данные. Это действие невозможно отменить.",
|
||||||
|
"gen_invite": "Сгенерировать ссылку-приглашение",
|
||||||
|
"group_settings_sub": "Настройки общей группы. Для применения изменений возможно потребуется перезагрузить страницу."
|
||||||
|
}
|
||||||
|
}
|
||||||
128
frontend/locales/sv.json
Normal file
128
frontend/locales/sv.json
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
{
|
||||||
|
"profile": {
|
||||||
|
"notifier_modal": "{ type, select, true {Edit} false {Create} other {Other}} Anmälare",
|
||||||
|
"change_password": "Ändra Lösenord",
|
||||||
|
"current_password": "Nuvarande lösenord",
|
||||||
|
"new_password": "Nytt lösenord",
|
||||||
|
"notifiers_sub": "Få aviseringar om kommande underhållspåminnelser",
|
||||||
|
"url": "URL",
|
||||||
|
"test": "Test",
|
||||||
|
"gen_invite": "Skapa inbjudningslänk",
|
||||||
|
"user_profile": "Användarprofil",
|
||||||
|
"user_profile_sub": "Bjud in användare och hantera ditt konto.",
|
||||||
|
"active": "Aktiv",
|
||||||
|
"inactive": "Inaktiv",
|
||||||
|
"notifiers": "Notiser",
|
||||||
|
"enabled": "Aktiverad",
|
||||||
|
"currency_format": "Valuta format",
|
||||||
|
"delete_account": "Radera konto",
|
||||||
|
"delete_account_sub": "Ta bort ditt konto och alla tillhörande data. Detta kan inte ångras.",
|
||||||
|
"group_settings": "Grupp inställningar",
|
||||||
|
"group_settings_sub": "Inställningar för delad grupp. Du kan behöva uppdatera din webbläsare för att vissa inställningar ska gälla.",
|
||||||
|
"theme_settings": "Temainställningar",
|
||||||
|
"theme_settings_sub": "Temainställningar sparas i din webbläsares lokala lagring. Du kan ändra tema när du vill. Om du\nhar problem att ställa in tema, pröva att ladda om din webbläsare.",
|
||||||
|
"update_group": "Uppdatera grupp"
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"set_name": "Vad heter du?",
|
||||||
|
"joining_group": "Du går med i en befintlig grupp!",
|
||||||
|
"dont_join_group": "Vill du inte gå med i en grupp?",
|
||||||
|
"tagline": "Spåra, organisera och hantera dina saker.",
|
||||||
|
"disabled_registration": "Registrering avaktiverad",
|
||||||
|
"login": "Logga in",
|
||||||
|
"register": "Registrera",
|
||||||
|
"remember_me": "Kom ihåg mig",
|
||||||
|
"set_email": "Vad är din e-post?",
|
||||||
|
"set_password": "Ställ in ditt lösenord"
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"app": {
|
||||||
|
"import_dialog": {
|
||||||
|
"upload": "Ladda upp",
|
||||||
|
"title": "Importera CSV fil",
|
||||||
|
"description": "Importera en CSV-fil som innehåller dina föremål, etiketter och platser. Se dokumentationen för mer information om \nönskat format.",
|
||||||
|
"change_warning": "Beteendet för importer med befintliga import_refs har ändrats. Om en import_ref finns i CSV-filen, \nobjektet kommer att uppdateras med värdena i CSV-filen."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"item": {
|
||||||
|
"view": {
|
||||||
|
"selectable": {
|
||||||
|
"card": "Kort",
|
||||||
|
"items": "Föremål",
|
||||||
|
"table": "Tabell",
|
||||||
|
"no_items": "Inga föremål att visa"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Skapa föremål",
|
||||||
|
"photo_button": "Foto 📷"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Skapa etikett"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Skapa plats"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"global": {
|
||||||
|
"password_score": {
|
||||||
|
"password_strength": "Lösenordsstyrka"
|
||||||
|
},
|
||||||
|
"page_qr_code": {
|
||||||
|
"page_url": "Sidans URL"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"global": {
|
||||||
|
"build": "Byggd: { build }",
|
||||||
|
"github": "GitHub Projekt",
|
||||||
|
"join_discord": "Gå med i Discord",
|
||||||
|
"follow_dev": "Följ utvecklaren",
|
||||||
|
"read_docs": "Läs dokumenten",
|
||||||
|
"password": "Lösenord",
|
||||||
|
"email": "Epost",
|
||||||
|
"submit": "Skicka",
|
||||||
|
"confirm": "Godkänn",
|
||||||
|
"create": "Skapa",
|
||||||
|
"created": "Skapad",
|
||||||
|
"welcome": "Välkommen, { username }",
|
||||||
|
"sign_out": "Logga ut",
|
||||||
|
"create_and_add": "Skapa och lägg till en annan",
|
||||||
|
"version": "Version: { version }",
|
||||||
|
"items": "Föremål",
|
||||||
|
"labels": "Etiketter",
|
||||||
|
"locations": "Platser",
|
||||||
|
"name": "Namn",
|
||||||
|
"search": "Sök"
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"add": "Lägg till",
|
||||||
|
"created_at": "Skapat",
|
||||||
|
"custom_fields": "Egna fält",
|
||||||
|
"field_selector": "Fält alternativ",
|
||||||
|
"field_value": "Fält värde",
|
||||||
|
"first": "Första",
|
||||||
|
"include_archive": "Inkludera arkiverade föremål",
|
||||||
|
"last": "Sista",
|
||||||
|
"negate_labels": "Negera valda etiketter",
|
||||||
|
"next_page": "Nästa sida",
|
||||||
|
"no_results": "Inga föremål hittades",
|
||||||
|
"options": "Alternativ",
|
||||||
|
"order_by": "Ordning via",
|
||||||
|
"pages": "Sida { page } av { totalPages }",
|
||||||
|
"prev_page": "Föregående sida",
|
||||||
|
"query_id": "Fråga efter tillgångs-ID-nummer: { id }",
|
||||||
|
"reset_search": "Återställ sökning",
|
||||||
|
"tip_1": "Platser och etiketter filter använder 'OR' funktionen. Om fler än en är valda, endast en kommer\nkrävas för en träff.",
|
||||||
|
"tip_2": "Sökningar med prefixet '#'' kommer att fråga efter ett tillgångs-ID (exempel '#000-001')",
|
||||||
|
"tip_3": "Fältfilter använder 'OR' funktion. Om fler än en är valda endast en kommer att bli krävande för en\nträff.",
|
||||||
|
"tips": "Tips",
|
||||||
|
"tips_sub": "Sök Tips",
|
||||||
|
"updated_at": "Uppdaterad",
|
||||||
|
"results": "{ total } Resultat"
|
||||||
|
}
|
||||||
|
}
|
||||||
128
frontend/locales/tr.json
Normal file
128
frontend/locales/tr.json
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
{
|
||||||
|
"global": {
|
||||||
|
"version": "Versiyon:{ version }",
|
||||||
|
"password": "Şifre",
|
||||||
|
"create": "Oluştur",
|
||||||
|
"github": "GitHub projesi",
|
||||||
|
"join_discord": "Discord'a Katılın",
|
||||||
|
"follow_dev": "Geliştiriciyi takip edin",
|
||||||
|
"read_docs": "Dokümanları okuyun",
|
||||||
|
"email": "Elektronik posta",
|
||||||
|
"submit": "Gönder",
|
||||||
|
"confirm": "Onaylayın",
|
||||||
|
"build": "Sürüm: { build }",
|
||||||
|
"create_and_add": "Oluştur ve Bir Tane Daha Ekle",
|
||||||
|
"created": "Oluşturuldu",
|
||||||
|
"items": "Öğeler",
|
||||||
|
"labels": "Etiketler",
|
||||||
|
"locations": "Konumlar",
|
||||||
|
"name": "İsim",
|
||||||
|
"search": "Ara",
|
||||||
|
"sign_out": "Oturumu kapat",
|
||||||
|
"welcome": "Hoşgeldib, { username }"
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"app": {
|
||||||
|
"import_dialog": {
|
||||||
|
"change_warning": "Mevcut import_refs ile içe aktarmaların davranışı değişti. CSV dosyasında bir import_ref varsa, \nöğe CSV dosyasındaki değerlerle güncellenecektir.",
|
||||||
|
"title": "CSV dosyasını içeri aktar",
|
||||||
|
"upload": "Yükle",
|
||||||
|
"description": "Öğelerinizi, etiketlerinizi ve konumlarınızı içeren bir CSV dosyasını içe aktarın. Daha fazla\nbilgi için dökümanları okuyun."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"global": {
|
||||||
|
"password_score": {
|
||||||
|
"password_strength": "Şifre güvenlik seviyesi"
|
||||||
|
},
|
||||||
|
"page_qr_code": {
|
||||||
|
"page_url": "Sayfa URL'si"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"item": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Eşya Oluştur",
|
||||||
|
"photo_button": "Fotoğraf 📷"
|
||||||
|
},
|
||||||
|
"view": {
|
||||||
|
"selectable": {
|
||||||
|
"items": "Öğeler",
|
||||||
|
"card": "Kart",
|
||||||
|
"table": "Tablo",
|
||||||
|
"no_items": "Görüntülecek Öge Yok"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Etiket oluştur"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "Konum oluştur"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"remember_me": "Beni Hatırla",
|
||||||
|
"tagline": "Eşyalarınızı Takip Edin, Düzenleyin ve Yönetin.",
|
||||||
|
"disabled_registration": "Kayıt olma devre dışı",
|
||||||
|
"login": "Oturum Aç",
|
||||||
|
"register": "Kaydolun",
|
||||||
|
"set_email": "E-posta adresiniz nedir?",
|
||||||
|
"set_password": "Şifrenizi belirleyin",
|
||||||
|
"set_name": "Adın ne?",
|
||||||
|
"joining_group": "Mevcut bir gruba katılıyorsunuz!",
|
||||||
|
"dont_join_group": "Bir gruba katılmak istemiyor musunuz?"
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"add": "Ekle",
|
||||||
|
"created_at": "Oluşturulma",
|
||||||
|
"custom_fields": "Özel Alanlar",
|
||||||
|
"field_selector": "alan seçici",
|
||||||
|
"field_value": "Alan Değeri",
|
||||||
|
"first": "Birinci",
|
||||||
|
"include_archive": "Arşivlenen Öğeleri Dahil Et",
|
||||||
|
"last": "Son",
|
||||||
|
"negate_labels": "Seçili Etiketleri Yoksay",
|
||||||
|
"next_page": "Sonraki Sayfa",
|
||||||
|
"no_results": "Öğe Bulunamadı",
|
||||||
|
"options": "Seçenekler",
|
||||||
|
"order_by": "Sıralama ölçütü",
|
||||||
|
"pages": "Sayfa { page }/{ totalPages }",
|
||||||
|
"prev_page": "Önceki Sayfa",
|
||||||
|
"query_id": "Varlık Kimlik Numarası Sorgulanıyor: { id }",
|
||||||
|
"tip_1": "Konum ve etiket filtreleri 'veya' işlemini kullanır. Eğer birden fazla seçilirse sadece biri \neşleştirme için kullanılacaktır.",
|
||||||
|
"reset_search": "Aramayı Sıfırla",
|
||||||
|
"tips": "İpuçları",
|
||||||
|
"results": "{ total } Sonuç",
|
||||||
|
"tip_2": "'#' ile başlayan aramalar bir varlık kimliğini sorgular (örneğin '#000-001')",
|
||||||
|
"tip_3": "Alan filtreleri 'VEYA' işlemini kullanır. Birden fazla seçenek seçilirse, eşleşme için yalnızca birinin \nkarşılanması yeterlidir.",
|
||||||
|
"tips_sub": "Arama İpuçları",
|
||||||
|
"updated_at": "Güncellendiği Zaman"
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"url": "URL",
|
||||||
|
"user_profile": "Kullanıcı Profili",
|
||||||
|
"user_profile_sub": "Kullanıcıları davet edin ve hesabınızı yönetin.",
|
||||||
|
"active": "Aktif",
|
||||||
|
"change_password": "Şifre Değiştir",
|
||||||
|
"currency_format": "Para Birimi Biçimi",
|
||||||
|
"current_password": "Mevcut Şifre",
|
||||||
|
"delete_account": "Hesabı Sil",
|
||||||
|
"delete_account_sub": "Hesabınızı ve ona bağlı tüm verileri silin. Bu işlem geri alınamaz.",
|
||||||
|
"enabled": "Etkinleştirildi",
|
||||||
|
"gen_invite": "Davet Bağlantısı Oluştur",
|
||||||
|
"group_settings": "Grup Ayarları",
|
||||||
|
"group_settings_sub": "Paylaşılan Grup Ayarları. Bazı ayarların uygulanabilmesi için tarayıcınızı yenilemeniz gerekebilir.",
|
||||||
|
"inactive": "Etkin Değil",
|
||||||
|
"new_password": "Yeni Şifre",
|
||||||
|
"notifier_modal": "{ type, select, true {Edit} false {Create} other {Other}} Bildirici",
|
||||||
|
"notifiers": "Bildirimde Bulunanlar",
|
||||||
|
"test": "Test",
|
||||||
|
"theme_settings": "Tema Ayarları",
|
||||||
|
"theme_settings_sub": "Tema ayarları tarayıcınızın yerel depolama alanında saklanır. Temayı istediğiniz zaman değiştirebilirsiniz. \nTemanızı ayarlamakta sorun yaşıyorsanız, tarayıcınızı yenilemeyi deneyin.",
|
||||||
|
"update_group": "Grubu Güncelle",
|
||||||
|
"notifiers_sub": "Yaklaşan bakım hatırlatmaları için bildirimler alın"
|
||||||
|
}
|
||||||
|
}
|
||||||
128
frontend/locales/zh_Hans.json
Normal file
128
frontend/locales/zh_Hans.json
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
{
|
||||||
|
"components": {
|
||||||
|
"app": {
|
||||||
|
"import_dialog": {
|
||||||
|
"title": "导入 CSV 文件",
|
||||||
|
"upload": "上传",
|
||||||
|
"description": "导入包含物品、标签和位置的CSV文件。更多有关信息,\n请参阅文档查看所需格式。",
|
||||||
|
"change_warning": "导入行为会导致现有的 import_refs 的字段被覆盖。\n如果 CSV 文件中存在 import_ref,则将使用 CSV 文件中的值更新该项。"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"item": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "创建物品",
|
||||||
|
"photo_button": "照片 📷"
|
||||||
|
},
|
||||||
|
"view": {
|
||||||
|
"selectable": {
|
||||||
|
"card": "卡片模式",
|
||||||
|
"items": "物品模式",
|
||||||
|
"no_items": "没有物品可用展示",
|
||||||
|
"table": "表格模式"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "创建位置"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"global": {
|
||||||
|
"page_qr_code": {
|
||||||
|
"page_url": "页面URL"
|
||||||
|
},
|
||||||
|
"password_score": {
|
||||||
|
"password_strength": "密码强度"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "创建标签"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"global": {
|
||||||
|
"create_and_add": "保存并继续创建",
|
||||||
|
"email": "邮箱",
|
||||||
|
"items": "物品",
|
||||||
|
"build": "编译:{build}",
|
||||||
|
"confirm": "确认",
|
||||||
|
"create": "创建",
|
||||||
|
"created": "已创建",
|
||||||
|
"follow_dev": "关注开发者",
|
||||||
|
"github": "Github项目",
|
||||||
|
"join_discord": "加入Discord讨论",
|
||||||
|
"labels": "标签",
|
||||||
|
"sign_out": "注销",
|
||||||
|
"version": "版本:{version}",
|
||||||
|
"welcome": "欢迎,{username}",
|
||||||
|
"name": "名称",
|
||||||
|
"password": "密码",
|
||||||
|
"read_docs": "查阅文档",
|
||||||
|
"search": "搜索",
|
||||||
|
"submit": "提交",
|
||||||
|
"locations": "位置"
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"disabled_registration": "已禁用注册",
|
||||||
|
"dont_join_group": "不想加入群组?",
|
||||||
|
"joining_group": "您正在加入现有群组!",
|
||||||
|
"login": "登录",
|
||||||
|
"register": "注册",
|
||||||
|
"set_name": "你的名称叫什么?",
|
||||||
|
"remember_me": "记住我",
|
||||||
|
"set_email": "您的电子邮箱是什么?",
|
||||||
|
"tagline": "跟踪、整理和管理您的物品。",
|
||||||
|
"set_password": "设置密码"
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"last": "最后一页",
|
||||||
|
"negate_labels": "取消选中的标签",
|
||||||
|
"next_page": "下一页",
|
||||||
|
"no_results": "没有可显示的物品",
|
||||||
|
"options": "选项",
|
||||||
|
"prev_page": "上一页",
|
||||||
|
"add": "添加",
|
||||||
|
"field_selector": "字段选择",
|
||||||
|
"first": "第一页",
|
||||||
|
"order_by": "排序方式",
|
||||||
|
"pages": "第{page}页,共{totalPages}页",
|
||||||
|
"query_id": "查询资产ID: {id}",
|
||||||
|
"created_at": "创建于",
|
||||||
|
"custom_fields": "自定义字段",
|
||||||
|
"field_value": "字段值",
|
||||||
|
"include_archive": "包括已存档的项目",
|
||||||
|
"reset_search": "重置搜索",
|
||||||
|
"results": "{ total } 条结果",
|
||||||
|
"tip_1": "位置和标签过滤器使用“或”操作。如果选择了多个位置或标签,\n则只需要任意一个匹配上即可。",
|
||||||
|
"tip_2": "以“#”为前缀的搜索将变成查询资产ID(例如“#000-001” )",
|
||||||
|
"tip_3": "字段过滤器使用“或”操作。如果选择了多个位置或标签,\n则只需要任意一个匹配上即可。",
|
||||||
|
"tips": "建议",
|
||||||
|
"tips_sub": "搜索提示",
|
||||||
|
"updated_at": "更新于"
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"group_settings_sub": "共享组设置。您可能需要刷新浏览器来让某些设置生效。",
|
||||||
|
"notifier_modal": "通知 { type, select, true {Edit} false {Create} other {Other}}",
|
||||||
|
"active": "活跃",
|
||||||
|
"delete_account_sub": "删除您的帐户及其所有相关数据。这是无法撤消的。",
|
||||||
|
"inactive": "非活跃",
|
||||||
|
"theme_settings_sub": "主题设置存储在浏览器的本地存储中。您可以随时更改主题。\n如果您在设置主题时遇到问题,请尝试刷新浏览器。",
|
||||||
|
"update_group": "更新组",
|
||||||
|
"change_password": "更改密码",
|
||||||
|
"currency_format": "货币格式",
|
||||||
|
"current_password": "原密码",
|
||||||
|
"delete_account": "删除帐户",
|
||||||
|
"enabled": "已启用",
|
||||||
|
"gen_invite": "生成邀请链接",
|
||||||
|
"group_settings": "组设置",
|
||||||
|
"new_password": "新密码",
|
||||||
|
"notifiers": "通知",
|
||||||
|
"notifiers_sub": "获取即将到来的维护提醒通知",
|
||||||
|
"test": "测试",
|
||||||
|
"theme_settings": "主题设置",
|
||||||
|
"url": "网址",
|
||||||
|
"user_profile": "用户资料",
|
||||||
|
"user_profile_sub": "邀请用户共同管理您的资产。"
|
||||||
|
}
|
||||||
|
}
|
||||||
128
frontend/locales/zh_Hant.json
Normal file
128
frontend/locales/zh_Hant.json
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
{
|
||||||
|
"items": {
|
||||||
|
"include_archive": "包括存檔項目",
|
||||||
|
"tip_1": "位置和標籤過濾器使用“OR”運算。如果選擇了多個,則一次配對\n只會使用一個。",
|
||||||
|
"pages": "第{ page } 頁(共{ totalPages })",
|
||||||
|
"tip_3": "字段過濾器使用“OR”運算。如果選擇了多個,則一次配對只需要選擇\n一個。",
|
||||||
|
"field_value": "欄位值",
|
||||||
|
"field_selector": "欄位選擇器",
|
||||||
|
"custom_fields": "自訂欄位",
|
||||||
|
"first": "第一項",
|
||||||
|
"add": "添加",
|
||||||
|
"created_at": "創建於",
|
||||||
|
"last": "最後一項",
|
||||||
|
"negate_labels": "取消選定的標籤",
|
||||||
|
"next_page": "下一頁",
|
||||||
|
"no_results": "沒有找到項目",
|
||||||
|
"options": "選項",
|
||||||
|
"order_by": "排序",
|
||||||
|
"prev_page": "上一頁",
|
||||||
|
"query_id": "查詢資產ID號碼:{ id }",
|
||||||
|
"reset_search": "重置搜尋",
|
||||||
|
"results": "{ total }結果",
|
||||||
|
"tips": "提示",
|
||||||
|
"tips_sub": "搜尋技巧",
|
||||||
|
"updated_at": "更新於",
|
||||||
|
"tip_2": "以「#」為前綴的搜尋將查詢資產 ID(例如「#000-001」)"
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"app": {
|
||||||
|
"import_dialog": {
|
||||||
|
"description": "匯入包含您的商品、標籤和位置的 CSV 檔案。有關所需格式的更多信息\n,請參閱文件。",
|
||||||
|
"title": "匯入CSV檔案",
|
||||||
|
"upload": "上傳",
|
||||||
|
"change_warning": "現有 import_refs 的導入行為已變更。如果 CSV 檔案中存在 import_ref,則\n項目將使用 CSV 檔案中的值進行更新。"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"global": {
|
||||||
|
"page_qr_code": {
|
||||||
|
"page_url": "頁面網址"
|
||||||
|
},
|
||||||
|
"password_score": {
|
||||||
|
"password_strength": "密碼強度"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"item": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "新增項目",
|
||||||
|
"photo_button": "相片 📷"
|
||||||
|
},
|
||||||
|
"view": {
|
||||||
|
"selectable": {
|
||||||
|
"card": "卡牌風",
|
||||||
|
"items": "項目",
|
||||||
|
"no_items": "沒有可顯示的項目",
|
||||||
|
"table": "表格"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "新增標籤"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"create_modal": {
|
||||||
|
"title": "新增地點"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"global": {
|
||||||
|
"build": "建立{ build }",
|
||||||
|
"confirm": "確認",
|
||||||
|
"create": "新增",
|
||||||
|
"create_and_add": "創建並添加另一個",
|
||||||
|
"created": "已建立",
|
||||||
|
"email": "電子信箱",
|
||||||
|
"github": "GitHub項目",
|
||||||
|
"items": "項目",
|
||||||
|
"join_discord": "加入Discord",
|
||||||
|
"labels": "標籤",
|
||||||
|
"locations": "地點",
|
||||||
|
"name": "名字",
|
||||||
|
"password": "密碼",
|
||||||
|
"read_docs": "閱讀文件",
|
||||||
|
"search": "搜尋",
|
||||||
|
"sign_out": "登出",
|
||||||
|
"submit": "提交",
|
||||||
|
"version": "版本:{ version }",
|
||||||
|
"follow_dev": "關注開發者",
|
||||||
|
"welcome": "歡迎,{ username }"
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"disabled_registration": "已禁用註冊",
|
||||||
|
"dont_join_group": "不想加入群組?",
|
||||||
|
"joining_group": "您正在加入現有群組!",
|
||||||
|
"login": "登入",
|
||||||
|
"register": "註冊",
|
||||||
|
"remember_me": "記住帳號",
|
||||||
|
"set_email": "你的電子郵件是什麼?",
|
||||||
|
"set_name": "你叫什麼名字?",
|
||||||
|
"tagline": "追蹤、組織和管理您的物品。",
|
||||||
|
"set_password": "設定您的密碼"
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"change_password": "變更密碼",
|
||||||
|
"currency_format": "貨幣格式",
|
||||||
|
"current_password": "當前密碼",
|
||||||
|
"delete_account": "刪除帳戶",
|
||||||
|
"enabled": "啟用",
|
||||||
|
"gen_invite": "產生邀請連結",
|
||||||
|
"group_settings": "群組設定",
|
||||||
|
"group_settings_sub": "共享群組設定。您可能需要刷新瀏覽器才能套用設定。",
|
||||||
|
"inactive": "不活躍",
|
||||||
|
"new_password": "新密碼",
|
||||||
|
"active": "活躍",
|
||||||
|
"delete_account_sub": "刪除您的帳戶及其所有相關資料。此操作無法撤回。",
|
||||||
|
"notifiers": "通知者",
|
||||||
|
"notifiers_sub": "獲取即將到來的維護提醒的通知",
|
||||||
|
"test": "測試",
|
||||||
|
"theme_settings": "主題設定",
|
||||||
|
"update_group": "更新群組",
|
||||||
|
"url": "網址",
|
||||||
|
"user_profile": "使用者資料",
|
||||||
|
"user_profile_sub": "邀請使用者並管理您的帳戶。",
|
||||||
|
"theme_settings_sub": "主題設定儲存在瀏覽器的本機儲存中。您可以隨時變更主題。如果你是\n 設定主題時遇到問題,請嘗試刷新瀏覽器。",
|
||||||
|
"notifier_modal": "通知 { type, select, true {Edit} false {Create} other {Other}}"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,9 @@ import { defineNuxtConfig } from "nuxt/config";
|
|||||||
// https://v3.nuxtjs.org/api/configuration/nuxt.config
|
// https://v3.nuxtjs.org/api/configuration/nuxt.config
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
ssr: false,
|
ssr: false,
|
||||||
|
build: {
|
||||||
|
transpile: ["vue-i18n"],
|
||||||
|
},
|
||||||
modules: [
|
modules: [
|
||||||
"@nuxtjs/tailwindcss",
|
"@nuxtjs/tailwindcss",
|
||||||
"@pinia/nuxt",
|
"@pinia/nuxt",
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@faker-js/faker": "^8.0.0",
|
"@faker-js/faker": "^8.0.0",
|
||||||
"@iconify-json/mdi": "^1.1.64",
|
"@iconify-json/mdi": "^1.1.64",
|
||||||
|
"@intlify/unplugin-vue-i18n": "^4.0.0",
|
||||||
"@nuxtjs/eslint-config-typescript": "^12.0.0",
|
"@nuxtjs/eslint-config-typescript": "^12.0.0",
|
||||||
"@types/dompurify": "^3.0.0",
|
"@types/dompurify": "^3.0.0",
|
||||||
"@types/markdown-it": "^13.0.0",
|
"@types/markdown-it": "^13.0.0",
|
||||||
@@ -27,13 +28,15 @@
|
|||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
"eslint-plugin-vue": "^9.4.0",
|
"eslint-plugin-vue": "^9.4.0",
|
||||||
"h3": "^1.7.1",
|
"h3": "^1.7.1",
|
||||||
|
"intl-messageformat": "^10.5.14",
|
||||||
"isomorphic-fetch": "^3.0.0",
|
"isomorphic-fetch": "^3.0.0",
|
||||||
"nuxt": "3.6.5",
|
"nuxt": "3.6.5",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"typescript": "^5.0.0",
|
"typescript": "^5.0.0",
|
||||||
"unplugin-icons": "^0.18.5",
|
"unplugin-icons": "^0.18.5",
|
||||||
"vite-plugin-eslint": "^1.8.1",
|
"vite-plugin-eslint": "^1.8.1",
|
||||||
"vitest": "^1.0.0"
|
"vitest": "^1.0.0",
|
||||||
|
"vue-i18n": "^9.13.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/vue": "^1.7.9",
|
"@headlessui/vue": "^1.7.9",
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import MdiGithub from "~icons/mdi/github";
|
import MdiGithub from "~icons/mdi/github";
|
||||||
import MdiTwitter from "~icons/mdi/twitter";
|
|
||||||
import MdiDiscord from "~icons/mdi/discord";
|
import MdiDiscord from "~icons/mdi/discord";
|
||||||
import MdiFolder from "~icons/mdi/folder";
|
import MdiFolder from "~icons/mdi/folder";
|
||||||
import MdiAccount from "~icons/mdi/account";
|
import MdiAccount from "~icons/mdi/account";
|
||||||
@@ -8,6 +7,7 @@
|
|||||||
import MdiLogin from "~icons/mdi/login";
|
import MdiLogin from "~icons/mdi/login";
|
||||||
import MdiArrowRight from "~icons/mdi/arrow-right";
|
import MdiArrowRight from "~icons/mdi/arrow-right";
|
||||||
import MdiLock from "~icons/mdi/lock";
|
import MdiLock from "~icons/mdi/lock";
|
||||||
|
import MdiMastodon from '~icons/mdi/mastodon';
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: "Homebox | Organize and Tag Your Stuff",
|
title: "Homebox | Organize and Tag Your Stuff",
|
||||||
@@ -77,6 +77,15 @@
|
|||||||
|
|
||||||
async function registerUser() {
|
async function registerUser() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|
||||||
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
|
||||||
|
if (!emailRegex.test(email.value)) {
|
||||||
|
toast.error("Invalid email address");
|
||||||
|
loading.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const { error } = await api.register({
|
const { error } = await api.register({
|
||||||
name: username.value,
|
name: username.value,
|
||||||
email: email.value,
|
email: email.value,
|
||||||
@@ -149,19 +158,19 @@
|
|||||||
<AppLogo class="w-12 -mb-4" />
|
<AppLogo class="w-12 -mb-4" />
|
||||||
x
|
x
|
||||||
</h2>
|
</h2>
|
||||||
<p class="ml-1 text-lg text-base-content/50">Track, Organize, and Manage your Things.</p>
|
<p class="ml-1 text-lg text-base-content/50">{{ $t("index.tagline") }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex mt-6 sm:mt-0 gap-4 ml-auto text-neutral-content">
|
<div class="flex mt-6 sm:mt-0 gap-4 ml-auto text-neutral-content">
|
||||||
<a class="tooltip" data-tip="Project Github" href="https://github.com/sysadminsmedia/homebox" target="_blank">
|
<a class="tooltip" :data-tip="$t('global.github')" href="https://github.com/sysadminsmedia/homebox" target="_blank">
|
||||||
<MdiGithub class="h-8 w-8" />
|
<MdiGithub class="h-8 w-8" />
|
||||||
</a>
|
</a>
|
||||||
<a href="https://twitter.com/haybytes" class="tooltip" data-tip="Follow The Developer" target="_blank">
|
<a href="https://noc.social/@sysadminsmedia" class="tooltip" :data-tip="$t('global.follow_dev')" target="_blank">
|
||||||
<MdiTwitter class="h-8 w-8" />
|
<MdiMastodon class="h-8 w-8" />
|
||||||
</a>
|
</a>
|
||||||
<a href="https://discord.gg/aY4DCkpNA9" class="tooltip" data-tip="Join The Discord" target="_blank">
|
<a href="https://discord.gg/aY4DCkpNA9" class="tooltip" :data-tip="$t('global.join_discord')" target="_blank">
|
||||||
<MdiDiscord class="h-8 w-8" />
|
<MdiDiscord class="h-8 w-8" />
|
||||||
</a>
|
</a>
|
||||||
<a href="https://homebox.sysadminsmedia.com/en/" class="tooltip" data-tip="Read The Docs" target="_blank">
|
<a href="https://homebox.sysadminsmedia.com/en/" class="tooltip" :data-tip="$t('global.read_docs')" target="_blank">
|
||||||
<MdiFolder class="h-8 w-8" />
|
<MdiFolder class="h-8 w-8" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -174,17 +183,17 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h2 class="card-title text-2xl align-center">
|
<h2 class="card-title text-2xl align-center">
|
||||||
<MdiAccount class="mr-1 w-7 h-7" />
|
<MdiAccount class="mr-1 w-7 h-7" />
|
||||||
Register
|
{{ $t("index.register") }}
|
||||||
</h2>
|
</h2>
|
||||||
<FormTextField v-model="email" label="Set your email?" />
|
<FormTextField v-model="email" :label="$t('index.set_email')" />
|
||||||
<FormTextField v-model="username" label="What's your name?" />
|
<FormTextField v-model="username" :label="$t('index.set_name')" />
|
||||||
<div v-if="!(groupToken == '')" class="pt-4 pb-1 text-center">
|
<div v-if="!(groupToken == '')" class="pt-4 pb-1 text-center">
|
||||||
<p>You're Joining an Existing Group!</p>
|
<p>{{ $t("index.joining_group") }}</p>
|
||||||
<button type="button" class="text-xs underline" @click="groupToken = ''">
|
<button type="button" class="text-xs underline" @click="groupToken = ''">
|
||||||
Don't Want To Join a Group?
|
{{ $t("index.dont_join_group") }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<FormPassword v-model="password" label="Set your password" />
|
<FormPassword v-model="password" :label="$t('index.set_password')" />
|
||||||
<PasswordScore v-model:valid="canRegister" :password="password" />
|
<PasswordScore v-model:valid="canRegister" :password="password" />
|
||||||
<div class="card-actions justify-end">
|
<div class="card-actions justify-end">
|
||||||
<button
|
<button
|
||||||
@@ -193,7 +202,7 @@
|
|||||||
:class="loading ? 'loading' : ''"
|
:class="loading ? 'loading' : ''"
|
||||||
:disabled="loading || !canRegister"
|
:disabled="loading || !canRegister"
|
||||||
>
|
>
|
||||||
Register
|
{{ $t("index.register") }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -204,17 +213,17 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h2 class="card-title text-2xl align-center">
|
<h2 class="card-title text-2xl align-center">
|
||||||
<MdiAccount class="mr-1 w-7 h-7" />
|
<MdiAccount class="mr-1 w-7 h-7" />
|
||||||
Login
|
{{ $t("index.login") }}
|
||||||
</h2>
|
</h2>
|
||||||
<template v-if="status && status.demo">
|
<template v-if="status && status.demo">
|
||||||
<p class="text-xs italic text-center">This is a demo instance</p>
|
<p class="text-xs italic text-center">This is a demo instance</p>
|
||||||
<p class="text-xs text-center"><b>Email</b> demo@example.com</p>
|
<p class="text-xs text-center"><b>{{ $t("global.email") }}</b> demo@example.com</p>
|
||||||
<p class="text-xs text-center"><b>Password</b> demo</p>
|
<p class="text-xs text-center"><b>{{ $t("global.password") }}</b> demo</p>
|
||||||
</template>
|
</template>
|
||||||
<FormTextField v-model="email" label="Email" />
|
<FormTextField v-model="email" :label="$t('global.email')" />
|
||||||
<FormPassword v-model="loginPassword" label="Password" />
|
<FormPassword v-model="loginPassword" :label="$t('global.password')" />
|
||||||
<div class="max-w-[140px]">
|
<div class="max-w-[140px]">
|
||||||
<FormCheckbox v-model="remember" label="Remember Me" />
|
<FormCheckbox v-model="remember" :label="$t('index.remember_me')" />
|
||||||
</div>
|
</div>
|
||||||
<div class="card-actions justify-end">
|
<div class="card-actions justify-end">
|
||||||
<button
|
<button
|
||||||
@@ -223,7 +232,7 @@
|
|||||||
:class="loading ? 'loading' : ''"
|
:class="loading ? 'loading' : ''"
|
||||||
:disabled="loading"
|
:disabled="loading"
|
||||||
>
|
>
|
||||||
Login
|
{{ $t("index.login") }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -241,18 +250,21 @@
|
|||||||
<MdiLogin v-else class="w-5 h-5 swap-off" />
|
<MdiLogin v-else class="w-5 h-5 swap-off" />
|
||||||
<MdiArrowRight class="w-5 h-5 swap-on" />
|
<MdiArrowRight class="w-5 h-5 swap-on" />
|
||||||
</template>
|
</template>
|
||||||
{{ registerForm ? "Login" : "Register" }}
|
{{ registerForm ? $t("index.login") : $t("index.register") }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<p v-else class="text-base-content italic text-sm inline-flex items-center gap-2">
|
<p v-else class="text-base-content italic text-sm inline-flex items-center gap-2">
|
||||||
<MdiLock class="w-4 h-4 inline-block" />
|
<MdiLock class="w-4 h-4 inline-block" />
|
||||||
Registration Disabled
|
{{ $t("disabled_registration") }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<footer v-if="status" class="mt-auto text-center w-full bottom-0 pb-4">
|
<footer v-if="status" class="mt-auto text-center w-full bottom-0 pb-4">
|
||||||
<p class="text-center text-sm">Version: {{ status.build.version }} ~ Build: {{ status.build.commit }}</p>
|
<p class="text-center text-sm">
|
||||||
|
{{ $t("global.version", { version: status.build.version }) }} ~
|
||||||
|
{{ $t("global.build", { build: status.build.commit }) }}
|
||||||
|
</p>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -338,9 +338,9 @@
|
|||||||
<div v-if="locations && labels">
|
<div v-if="locations && labels">
|
||||||
<div class="flex flex-wrap md:flex-nowrap gap-4 items-end">
|
<div class="flex flex-wrap md:flex-nowrap gap-4 items-end">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<FormTextField v-model="query" placeholder="Search" />
|
<FormTextField v-model="query" :placeholder="$t('global.search')" />
|
||||||
<div v-if="byAssetId" class="text-sm pl-2 pt-2">
|
<div v-if="byAssetId" class="text-sm pl-2 pt-2">
|
||||||
<p>Querying Asset ID Number: {{ parsedAssetId }}</p>
|
<p>{{ $t("items.query_id", { id: parsedAssetId }) }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<BaseButton class="btn-block md:w-auto" @click.prevent="submit">
|
<BaseButton class="btn-block md:w-auto" @click.prevent="submit">
|
||||||
@@ -348,12 +348,12 @@
|
|||||||
<MdiLoading v-if="loading" class="animate-spin" />
|
<MdiLoading v-if="loading" class="animate-spin" />
|
||||||
<MdiMagnify v-else />
|
<MdiMagnify v-else />
|
||||||
</template>
|
</template>
|
||||||
Search
|
{{ $t("global.search") }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap md:flex-nowrap gap-2 w-full py-2">
|
<div class="flex flex-wrap md:flex-nowrap gap-2 w-full py-2">
|
||||||
<SearchFilter v-model="selectedLocations" label="Locations" :options="locationFlatTree">
|
<SearchFilter v-model="selectedLocations" :label="$t('global.locations')" :options="locationFlatTree">
|
||||||
<template #display="{ item }">
|
<template #display="{ item }">
|
||||||
<div>
|
<div>
|
||||||
<div class="flex w-full">
|
<div class="flex w-full">
|
||||||
@@ -365,60 +365,60 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</SearchFilter>
|
</SearchFilter>
|
||||||
<SearchFilter v-model="selectedLabels" label="Labels" :options="labels" />
|
<SearchFilter v-model="selectedLabels" :label="$t('global.labels')" :options="labels" />
|
||||||
<div class="dropdown">
|
<div class="dropdown">
|
||||||
<label tabindex="0" class="btn btn-xs">Options</label>
|
<label tabindex="0" class="btn btn-xs">{{ $t("items.options") }}</label>
|
||||||
<div
|
<div
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
class="dropdown-content mt-1 max-h-72 p-4 w-64 overflow-auto shadow bg-base-100 rounded-md -translate-x-24"
|
class="dropdown-content mt-1 max-h-72 p-4 w-64 overflow-auto shadow bg-base-100 rounded-md -translate-x-24"
|
||||||
>
|
>
|
||||||
<label class="label cursor-pointer mr-auto">
|
<label class="label cursor-pointer mr-auto">
|
||||||
<input v-model="includeArchived" type="checkbox" class="toggle toggle-sm toggle-primary" />
|
<input v-model="includeArchived" type="checkbox" class="toggle toggle-sm toggle-primary" />
|
||||||
<span class="label-text ml-4"> Include Archived Items </span>
|
<span class="label-text ml-4"> {{ $t("items.include_archive") }} </span>
|
||||||
</label>
|
</label>
|
||||||
<label class="label cursor-pointer mr-auto">
|
<label class="label cursor-pointer mr-auto">
|
||||||
<input v-model="fieldSelector" type="checkbox" class="toggle toggle-sm toggle-primary" />
|
<input v-model="fieldSelector" type="checkbox" class="toggle toggle-sm toggle-primary" />
|
||||||
<span class="label-text ml-4"> Field Selector </span>
|
<span class="label-text ml-4"> {{ $t("items.field_selector") }} </span>
|
||||||
</label>
|
</label>
|
||||||
<label class="label cursor-pointer mr-auto">
|
<label class="label cursor-pointer mr-auto">
|
||||||
<input v-model="negateLabels" type="checkbox" class="toggle toggle-sm toggle-primary" />
|
<input v-model="negateLabels" type="checkbox" class="toggle toggle-sm toggle-primary" />
|
||||||
<span class="label-text ml-4"> Negate selected labels </span>
|
<span class="label-text ml-4"> {{ $t("items.negate_labels") }} </span>
|
||||||
</label>
|
</label>
|
||||||
<label class="label cursor-pointer mr-auto">
|
<label class="label cursor-pointer mr-auto">
|
||||||
<select v-model="orderBy" class="select select-bordered select-sm">
|
<select v-model="orderBy" class="select select-bordered select-sm">
|
||||||
<option value="name" selected>Name</option>
|
<option value="name" selected>{{ $t("global.name") }}</option>
|
||||||
<option value="createdAt">Created At</option>
|
<option value="createdAt">{{ $t("items.created_at") }}</option>
|
||||||
<option value="updatedAt">Updated At</option>
|
<option value="updatedAt">{{ $t("items.updated_at") }}</option>
|
||||||
</select>
|
</select>
|
||||||
<span class="label-text ml-4"> Order By </span>
|
<span class="label-text ml-4"> {{ $t("items.order_by") }} </span>
|
||||||
</label>
|
</label>
|
||||||
<hr class="my-2" />
|
<hr class="my-2" />
|
||||||
<BaseButton class="btn-block btn-sm" @click="reset"> Reset Search</BaseButton>
|
<BaseButton class="btn-block btn-sm" @click="reset"> {{ $t("items.reset_search") }} </BaseButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="dropdown ml-auto dropdown-end">
|
<div class="dropdown ml-auto dropdown-end">
|
||||||
<label tabindex="0" class="btn btn-xs">Tips</label>
|
<label tabindex="0" class="btn btn-xs">{{ $t("items.tips") }}</label>
|
||||||
<div
|
<div
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
class="dropdown-content mt-1 p-4 w-[325px] text-sm overflow-auto shadow bg-base-100 rounded-md"
|
class="dropdown-content mt-1 p-4 w-[325px] text-sm overflow-auto shadow bg-base-100 rounded-md"
|
||||||
>
|
>
|
||||||
<p class="text-base">Search Tips</p>
|
<p class="text-base">{{ $t("items.tips_sub") }}</p>
|
||||||
<ul class="mt-1 list-disc pl-6">
|
<ul class="mt-1 list-disc pl-6">
|
||||||
<li>
|
<li>
|
||||||
Location and label filters use the 'OR' operation. If more than one is selected only one will be
|
{{ $t("items.tip_1") }}
|
||||||
required for a match.
|
|
||||||
</li>
|
</li>
|
||||||
<li>Searches prefixed with '#'' will query for a asset ID (example '#000-001')</li>
|
|
||||||
<li>
|
<li>
|
||||||
Field filters use the 'OR' operation. If more than one is selected only one will be required for a
|
{{ $t("items.tip_2") }}
|
||||||
match.
|
</li>
|
||||||
|
<li>
|
||||||
|
{{ $t("items.tip_3") }}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="fieldSelector" class="py-4 space-y-2">
|
<div v-if="fieldSelector" class="py-4 space-y-2">
|
||||||
<p>Custom Fields</p>
|
<p>{{ $t("items.custom_fields") }}</p>
|
||||||
<div v-for="(f, idx) in fieldTuples" :key="idx" class="flex flex-wrap gap-2">
|
<div v-for="(f, idx) in fieldTuples" :key="idx" class="flex flex-wrap gap-2">
|
||||||
<div class="form-control w-full max-w-xs">
|
<div class="form-control w-full max-w-xs">
|
||||||
<label class="label">
|
<label class="label">
|
||||||
@@ -435,7 +435,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-control w-full max-w-xs">
|
<div class="form-control w-full max-w-xs">
|
||||||
<label class="label">
|
<label class="label">
|
||||||
<span class="label-text">Field Value</span>
|
<span class="label-text">{{ $t("items.field_value") }}</span>
|
||||||
</label>
|
</label>
|
||||||
<select v-model="fieldTuples[idx][1]" class="select-bordered select" :items="fieldValuesCache[f[0]]">
|
<select v-model="fieldTuples[idx][1]" class="select-bordered select" :items="fieldValuesCache[f[0]]">
|
||||||
<option v-for="v in fieldValuesCache[f[0]]" :key="v" :value="v">{{ v }}</option>
|
<option v-for="v in fieldValuesCache[f[0]]" :key="v" :value="v">{{ v }}</option>
|
||||||
@@ -449,38 +449,42 @@
|
|||||||
<MdiDelete class="w-5 h-5" />
|
<MdiDelete class="w-5 h-5" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<BaseButton type="button" class="btn-sm mt-2" @click="() => fieldTuples.push(['', ''])"> Add</BaseButton>
|
<BaseButton type="button" class="btn-sm mt-2" @click="() => fieldTuples.push(['', ''])">
|
||||||
|
{{ $t("items.add") }}
|
||||||
|
</BaseButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section class="mt-10">
|
<section class="mt-10">
|
||||||
<BaseSectionHeader ref="itemsTitle"> Items </BaseSectionHeader>
|
<BaseSectionHeader ref="itemsTitle"> {{ $t("global.items") }} </BaseSectionHeader>
|
||||||
<p class="text-base font-medium flex items-center">
|
<p class="text-base font-medium flex items-center">
|
||||||
{{ total }} Results
|
{{ $t("items.results", { total: total }) }}
|
||||||
<span class="text-base ml-auto"> Page {{ page }} of {{ totalPages }}</span>
|
<span class="text-base ml-auto"> {{ $t("items.pages", { page: page, totalPages: totalPages }) }} </span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div ref="cardgrid" class="grid mt-4 grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
|
<div ref="cardgrid" class="grid mt-4 grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
|
||||||
<ItemCard v-for="item in items" :key="item.id" :item="item" />
|
<ItemCard v-for="item in items" :key="item.id" :item="item" />
|
||||||
|
|
||||||
<div class="hidden first:inline text-xl">No Items Found</div>
|
<div class="hidden first:inline text-xl">{{ $t("items.no_results") }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="items.length > 0 && (hasNext || hasPrev)" class="mt-10 flex gap-2 flex-col items-center">
|
<div v-if="items.length > 0 && (hasNext || hasPrev)" class="mt-10 flex gap-2 flex-col items-center">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<button :disabled="!hasPrev" class="btn text-no-transform" @click="prev">
|
<button :disabled="!hasPrev" class="btn text-no-transform" @click="prev">
|
||||||
<MdiChevronLeft class="mr-1 h-6 w-6" name="mdi-chevron-left" />
|
<MdiChevronLeft class="mr-1 h-6 w-6" name="mdi-chevron-left" />
|
||||||
Prev
|
{{ $t("items.prev_page") }}
|
||||||
|
</button>
|
||||||
|
<button v-if="hasPrev" class="btn text-no-transform" @click="page = 1">{{ $t("items.first") }}</button>
|
||||||
|
<button v-if="hasNext" class="btn text-no-transform" @click="page = totalPages">
|
||||||
|
{{ $t("items.last") }}
|
||||||
</button>
|
</button>
|
||||||
<button v-if="hasPrev" class="btn text-no-transform" @click="page = 1">First</button>
|
|
||||||
<button v-if="hasNext" class="btn text-no-transform" @click="page = totalPages">Last</button>
|
|
||||||
<button :disabled="!hasNext" class="btn text-no-transform" @click="next">
|
<button :disabled="!hasNext" class="btn text-no-transform" @click="next">
|
||||||
Next
|
{{ $t("items.next_page") }}
|
||||||
<MdiChevronRight class="ml-1 h-6 w-6" name="mdi-chevron-right" />
|
<MdiChevronRight class="ml-1 h-6 w-6" name="mdi-chevron-right" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-sm font-bold">Page {{ page }} of {{ totalPages }}</p>
|
<p class="text-sm font-bold">{{ $t("items.pages", { page: page, totalPages: totalPages }) }}</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</BaseContainer>
|
</BaseContainer>
|
||||||
|
|||||||
@@ -89,13 +89,6 @@
|
|||||||
notify.success("Group updated");
|
notify.success("Group updated");
|
||||||
}
|
}
|
||||||
|
|
||||||
const pubApi = usePublicApi();
|
|
||||||
const { data: status } = useAsyncData(async () => {
|
|
||||||
const { data } = await pubApi.status();
|
|
||||||
|
|
||||||
return data;
|
|
||||||
});
|
|
||||||
|
|
||||||
const { setTheme } = useTheme();
|
const { setTheme } = useTheme();
|
||||||
|
|
||||||
const auth = useAuthContext();
|
const auth = useAuthContext();
|
||||||
@@ -305,11 +298,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<BaseModal v-model="passwordChange.dialog">
|
<BaseModal v-model="passwordChange.dialog">
|
||||||
<template #title> Change Password </template>
|
<template #title> {{ $t("profile.change_password") }} </template>
|
||||||
|
|
||||||
<form @submit.prevent="changePassword">
|
<form @submit.prevent="changePassword">
|
||||||
<FormPassword v-model="passwordChange.current" label="Current Password" placeholder="" />
|
<FormPassword v-model="passwordChange.current" :label="$t('profile.current_password')" placeholder="" />
|
||||||
<FormPassword v-model="passwordChange.new" label="New Password" placeholder="" />
|
<FormPassword v-model="passwordChange.new" :label="$t('profile.new_password')" placeholder="" />
|
||||||
<PasswordScore v-model:valid="passwordChange.isValid" :password="passwordChange.new" />
|
<PasswordScore v-model:valid="passwordChange.isValid" :password="passwordChange.new" />
|
||||||
|
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
@@ -319,26 +312,26 @@
|
|||||||
:disabled="!passwordChange.isValid"
|
:disabled="!passwordChange.isValid"
|
||||||
type="submit"
|
type="submit"
|
||||||
>
|
>
|
||||||
Submit
|
{{ $t("global.submit") }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
|
|
||||||
<BaseModal v-model="notifierDialog">
|
<BaseModal v-model="notifierDialog">
|
||||||
<template #title> {{ notifier ? "Edit" : "Create" }} Notifier </template>
|
<template #title> {{ $t("profile.notifier_modal", {type: (notifier != null)}) }} </template>
|
||||||
|
|
||||||
<form @submit.prevent="createNotifier">
|
<form @submit.prevent="createNotifier">
|
||||||
<template v-if="notifier">
|
<template v-if="notifier">
|
||||||
<FormTextField v-model="notifier.name" label="Name" />
|
<FormTextField v-model="notifier.name" :label="$t('global.name')" />
|
||||||
<FormTextField v-model="notifier.url" label="URL" />
|
<FormTextField v-model="notifier.url" :label="$t('profile.url')" />
|
||||||
<div class="max-w-[100px]">
|
<div class="max-w-[100px]">
|
||||||
<FormCheckbox v-model="notifier.isActive" label="Enabled" />
|
<FormCheckbox v-model="notifier.isActive" :label="$t('profile.enabled')" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="flex gap-2 justify-between mt-4">
|
<div class="flex gap-2 justify-between mt-4">
|
||||||
<BaseButton :disabled="!(notifier && notifier.url)" type="button" @click="testNotifier"> Test </BaseButton>
|
<BaseButton :disabled="!(notifier && notifier.url)" type="button" @click="testNotifier"> {{ $t("profile.test") }} </BaseButton>
|
||||||
<BaseButton type="submit"> Submit </BaseButton>
|
<BaseButton type="submit"> {{ $t("global.submit") }} </BaseButton>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
@@ -348,8 +341,8 @@
|
|||||||
<template #title>
|
<template #title>
|
||||||
<BaseSectionHeader>
|
<BaseSectionHeader>
|
||||||
<MdiAccount class="mr-2 -mt-1 text-base-600" />
|
<MdiAccount class="mr-2 -mt-1 text-base-600" />
|
||||||
<span class="text-base-600"> User Profile </span>
|
<span class="text-base-600"> {{ $t("profile.user_profile") }} </span>
|
||||||
<template #description> Invite users, and manage your account. </template>
|
<template #description> {{ $t("profile.user_profile_sub") }} </template>
|
||||||
</BaseSectionHeader>
|
</BaseSectionHeader>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -357,8 +350,8 @@
|
|||||||
|
|
||||||
<div class="p-4">
|
<div class="p-4">
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<BaseButton size="sm" @click="openPassChange"> Change Password </BaseButton>
|
<BaseButton size="sm" @click="openPassChange"> {{ $t("profile.change_password") }} </BaseButton>
|
||||||
<BaseButton size="sm" @click="generateToken"> Generate Invite Link </BaseButton>
|
<BaseButton size="sm" @click="generateToken"> {{ $t("profile.gen_invite") }} </BaseButton>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="token" class="pt-4 flex items-center pl-1">
|
<div v-if="token" class="pt-4 flex items-center pl-1">
|
||||||
<CopyText class="mr-2 btn-primary btn btn-outline btn-square btn-sm" :text="tokenUrl" />
|
<CopyText class="mr-2 btn-primary btn btn-outline btn-square btn-sm" :text="tokenUrl" />
|
||||||
@@ -375,8 +368,8 @@
|
|||||||
<template #title>
|
<template #title>
|
||||||
<BaseSectionHeader>
|
<BaseSectionHeader>
|
||||||
<MdiMegaphone class="mr-2 -mt-1 text-base-600" />
|
<MdiMegaphone class="mr-2 -mt-1 text-base-600" />
|
||||||
<span class="text-base-600"> Notifiers </span>
|
<span class="text-base-600"> {{ $t("profile.notifiers") }} </span>
|
||||||
<template #description> Get notifications for up coming maintenance reminders </template>
|
<template #description> {{ $t("profile.notifiers_sub") }} </template>
|
||||||
</BaseSectionHeader>
|
</BaseSectionHeader>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -399,11 +392,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between py-1 flex-wrap text-sm">
|
<div class="flex justify-between py-1 flex-wrap text-sm">
|
||||||
<p>
|
<p>
|
||||||
<span v-if="n.isActive" class="badge badge-success"> Active </span>
|
<span v-if="n.isActive" class="badge badge-success"> {{ $t("profile.active") }} </span>
|
||||||
<span v-else class="badge badge-error"> Inactive</span>
|
<span v-else class="badge badge-error"> {{ $t("profile.inactive") }} </span>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Created
|
{{ $t("global.created") }}
|
||||||
<DateTime format="relative" datetime-type="time" :date="n.createdAt" />
|
<DateTime format="relative" datetime-type="time" :date="n.createdAt" />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -411,7 +404,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="p-4">
|
<div class="p-4">
|
||||||
<BaseButton size="sm" @click="openNotifierDialog"> Create </BaseButton>
|
<BaseButton size="sm" @click="openNotifierDialog"> {{ $t("global.create") }} </BaseButton>
|
||||||
</div>
|
</div>
|
||||||
</BaseCard>
|
</BaseCard>
|
||||||
|
|
||||||
@@ -419,19 +412,19 @@
|
|||||||
<template #title>
|
<template #title>
|
||||||
<BaseSectionHeader class="pb-0">
|
<BaseSectionHeader class="pb-0">
|
||||||
<MdiAccountMultiple class="mr-2 -mt-1 text-base-600" />
|
<MdiAccountMultiple class="mr-2 -mt-1 text-base-600" />
|
||||||
<span class="text-base-600"> Group Settings </span>
|
<span class="text-base-600"> {{ $t("profile.group_settings") }} </span>
|
||||||
<template #description>
|
<template #description>
|
||||||
Shared Group Settings. You may need to refresh your browser for some settings to apply.
|
{{ $t("profile.group_settings_sub") }}
|
||||||
</template>
|
</template>
|
||||||
</BaseSectionHeader>
|
</BaseSectionHeader>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div v-if="group && currencies && currencies.length > 0" class="p-5 pt-0">
|
<div v-if="group && currencies && currencies.length > 0" class="p-5 pt-0">
|
||||||
<FormSelect v-model="currency" label="Currency Format" :items="currencies" />
|
<FormSelect v-model="currency" :label="$t('profile.currency_format')" :items="currencies" />
|
||||||
<p class="m-2 text-sm">Example: {{ currencyExample }}</p>
|
<p class="m-2 text-sm">Example: {{ currencyExample }}</p>
|
||||||
|
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<BaseButton size="sm" @click="updateGroup"> Update Group </BaseButton>
|
<BaseButton size="sm" @click="updateGroup"> {{ $t("profile.update_group") }} </BaseButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</BaseCard>
|
</BaseCard>
|
||||||
@@ -440,10 +433,9 @@
|
|||||||
<template #title>
|
<template #title>
|
||||||
<BaseSectionHeader>
|
<BaseSectionHeader>
|
||||||
<MdiFill class="mr-2 text-base-600" />
|
<MdiFill class="mr-2 text-base-600" />
|
||||||
<span class="text-base-600"> Theme Settings </span>
|
<span class="text-base-600"> {{ $t("profile.theme_settings") }} </span>
|
||||||
<template #description>
|
<template #description>
|
||||||
Theme settings are stored in your browser's local storage. You can change the theme at any time. If you're
|
{{ $t("profile.theme_settings_sub") }}
|
||||||
having trouble setting your theme try refreshing your browser.
|
|
||||||
</template>
|
</template>
|
||||||
</BaseSectionHeader>
|
</BaseSectionHeader>
|
||||||
</template>
|
</template>
|
||||||
@@ -491,18 +483,15 @@
|
|||||||
<template #title>
|
<template #title>
|
||||||
<BaseSectionHeader>
|
<BaseSectionHeader>
|
||||||
<MdiDelete class="mr-2 -mt-1 text-base-600" />
|
<MdiDelete class="mr-2 -mt-1 text-base-600" />
|
||||||
<span class="text-base-600"> Delete Account</span>
|
<span class="text-base-600"> {{ $t("profile.delete_account") }} </span>
|
||||||
<template #description> Delete your account and all its associated data. </template>
|
<template #description> {{ $t("profile.delete_account_sub") }} </template>
|
||||||
</BaseSectionHeader>
|
</BaseSectionHeader>
|
||||||
</template>
|
</template>
|
||||||
<div class="p-4 px-6 border-t-2 border-gray-300">
|
<div class="p-4 px-6 border-t-2 border-gray-300">
|
||||||
<BaseButton size="sm" class="btn-error" @click="deleteProfile"> Delete Account </BaseButton>
|
<BaseButton size="sm" class="btn-error" @click="deleteProfile"> {{ $t("profile.delete_account") }} </BaseButton>
|
||||||
</div>
|
</div>
|
||||||
</BaseCard>
|
</BaseCard>
|
||||||
</BaseContainer>
|
</BaseContainer>
|
||||||
<footer v-if="status" class="text-center w-full bottom-0 pb-4">
|
|
||||||
<p class="text-center text-sm">Version: {{ status.build.version }} ~ Build: {{ status.build.commit }}</p>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -308,7 +308,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
This feature is in early development stages and may change in future releases, if you have feedback please
|
This feature is in early development stages and may change in future releases, if you have feedback please
|
||||||
provide it in the <a href="https://github.com/sysadminsmedia/homebox/discussions/273">GitHub Discussion</a>
|
provide it in the <a href="https://github.com/sysadminsmedia/homebox/discussions/53">GitHub Discussion</a>
|
||||||
</p>
|
</p>
|
||||||
<h2>Tips</h2>
|
<h2>Tips</h2>
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
@@ -42,8 +42,9 @@
|
|||||||
<div class="border-t px-6 pb-3 border-gray-300 divide-gray-300 divide-y">
|
<div class="border-t px-6 pb-3 border-gray-300 divide-gray-300 divide-y">
|
||||||
<DetailAction @action="modals.import = true">
|
<DetailAction @action="modals.import = true">
|
||||||
<template #title>Import Inventory</template>
|
<template #title>Import Inventory</template>
|
||||||
Imports the standard CSV format for Homebox. This will <b>not</b> overwrite any existing items in your
|
Imports the standard CSV format for Homebox. Without an <code>HB.import_ref</code> column, this will
|
||||||
inventory. It will only add new items.
|
<b>not</b> overwrite any existing items in your inventory, only add new items. Rows with an
|
||||||
|
<code>HB.import_ref</code> column are merged into existing items with the same import_ref, if one exists.
|
||||||
</DetailAction>
|
</DetailAction>
|
||||||
<DetailAction @action="getExportCSV()">
|
<DetailAction @action="getExportCSV()">
|
||||||
<template #title>Export Inventory</template>
|
<template #title>Export Inventory</template>
|
||||||
@@ -104,7 +105,7 @@
|
|||||||
middleware: ["auth"],
|
middleware: ["auth"],
|
||||||
});
|
});
|
||||||
useHead({
|
useHead({
|
||||||
title: "Homebox | Profile",
|
title: "Homebox | Tools",
|
||||||
});
|
});
|
||||||
|
|
||||||
const modals = ref({
|
const modals = ref({
|
||||||
|
|||||||
63
frontend/plugins/i18n.ts
Normal file
63
frontend/plugins/i18n.ts
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import type { CompileError, MessageCompiler, MessageContext } from "vue-i18n";
|
||||||
|
import { createI18n } from "vue-i18n";
|
||||||
|
import { IntlMessageFormat } from "intl-messageformat";
|
||||||
|
|
||||||
|
export default defineNuxtPlugin(({ vueApp }) => {
|
||||||
|
function checkDefaultLanguage() {
|
||||||
|
let matched = null;
|
||||||
|
const languages = Object.getOwnPropertyNames(messages())
|
||||||
|
languages.forEach(lang => {
|
||||||
|
if (lang === navigator.language) {
|
||||||
|
matched = lang;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!matched) {
|
||||||
|
languages.forEach(lang => {
|
||||||
|
const languagePartials = navigator.language.split('-')[0]
|
||||||
|
if (lang === languagePartials) {
|
||||||
|
matched = lang;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return matched;
|
||||||
|
}
|
||||||
|
const i18n = createI18n({
|
||||||
|
legacy: false,
|
||||||
|
globalInjection: true,
|
||||||
|
locale: checkDefaultLanguage() || "en",
|
||||||
|
fallbackLocale: "en",
|
||||||
|
messageCompiler,
|
||||||
|
messages: messages(),
|
||||||
|
});
|
||||||
|
vueApp.use(i18n);
|
||||||
|
});
|
||||||
|
|
||||||
|
export const messageCompiler: MessageCompiler = (message, { locale, key, onError }) => {
|
||||||
|
if (typeof message === "string") {
|
||||||
|
/**
|
||||||
|
* You can tune your message compiler performance more with your cache strategy or also memoization at here
|
||||||
|
*/
|
||||||
|
const formatter = new IntlMessageFormat(message, locale);
|
||||||
|
return (ctx: MessageContext) => {
|
||||||
|
return formatter.format(ctx.values);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
/**
|
||||||
|
* for AST.
|
||||||
|
* If you would like to support it,
|
||||||
|
* You need to transform locale messages such as `json`, `yaml`, etc. with the bundle plugin.
|
||||||
|
*/
|
||||||
|
onError && onError(new Error("not support for AST") as CompileError);
|
||||||
|
return () => key;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const messages: Object = () => {
|
||||||
|
let messages = {};
|
||||||
|
const modules = import.meta.glob('~//locales/**.json', { eager: true });
|
||||||
|
for (const path in modules) {
|
||||||
|
const key = path.slice(9, -5);
|
||||||
|
messages[key] = modules[path];
|
||||||
|
}
|
||||||
|
return messages;
|
||||||
|
};
|
||||||
12434
frontend/pnpm-lock.yaml
generated
12434
frontend/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user