- Added standard Laravel directory structure and configuration. - Included Svelte and Tailwind configuration for the admin interface. - Added core PHPUnit and testing scripts.
193 lines
7.2 KiB
Svelte
193 lines
7.2 KiB
Svelte
<script>
|
|
let { adminPath, locale = 'en', overrides = [], availableLocales = ['en', 'es', 'fr', 'de'] } = $props();
|
|
|
|
let items = $state([]);
|
|
let newLocale = $state('en');
|
|
let newGroup = $state('cms');
|
|
let newKey = $state('');
|
|
let newValue = $state('');
|
|
|
|
$effect(() => {
|
|
items = overrides;
|
|
newLocale = locale;
|
|
});
|
|
|
|
let loading = $state(false);
|
|
let message = $state(null);
|
|
|
|
async function saveTranslation(item = null) {
|
|
loading = true;
|
|
message = null;
|
|
|
|
const data = item ? {
|
|
locale: item.locale,
|
|
group: item.group,
|
|
key: item.key,
|
|
value: item.value
|
|
} : {
|
|
locale: newLocale,
|
|
group: newGroup,
|
|
key: newKey,
|
|
value: newValue
|
|
};
|
|
|
|
try {
|
|
const response = await fetch(`${adminPath}/translations`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
|
|
},
|
|
body: JSON.stringify(data)
|
|
});
|
|
|
|
if (response.ok) {
|
|
if (!item) {
|
|
items = [...items, { ...data, id: Date.now() }];
|
|
newKey = '';
|
|
newValue = '';
|
|
}
|
|
message = { type: 'success', text: 'Translation saved successfully!' };
|
|
} else {
|
|
message = { type: 'error', text: 'Failed to save translation.' };
|
|
}
|
|
} catch (error) {
|
|
message = { type: 'error', text: 'An error occurred.' };
|
|
} finally {
|
|
loading = false;
|
|
}
|
|
}
|
|
|
|
function switchLocale(l) {
|
|
window.location.href = `${adminPath}/translations?locale=${l}`;
|
|
}
|
|
</script>
|
|
|
|
<div class="ui container">
|
|
<div class="ui grid">
|
|
<div class="row">
|
|
<div class="column">
|
|
<h1 class="ui header">
|
|
<i class="language icon"></i>
|
|
<div class="content">
|
|
Translation Manager
|
|
<div class="sub header">Override system and plugin strings in the database.</div>
|
|
</div>
|
|
</h1>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="column">
|
|
<div class="ui segment">
|
|
<div class="ui form">
|
|
<div class="inline fields">
|
|
<span>Current Locale:</span>
|
|
{#each availableLocales as l}
|
|
<div class="field">
|
|
<button
|
|
type="button"
|
|
class="ui {locale === l ? 'primary' : ''} button"
|
|
onclick={() => switchLocale(l)}
|
|
>
|
|
{(l || '').toUpperCase()}
|
|
</button>
|
|
</div>
|
|
{/each}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{#if message}
|
|
<div class="row">
|
|
<div class="column">
|
|
<div class="ui {message.type} message">
|
|
{message.text}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{/if}
|
|
|
|
<div class="row">
|
|
<div class="column">
|
|
<div class="ui segment">
|
|
<h3 class="ui header">Add New Override</h3>
|
|
<div class="ui form">
|
|
<div class="four fields">
|
|
<div class="field">
|
|
<label for="newGroup">Group</label>
|
|
<input type="text" id="newGroup" bind:value={newGroup} placeholder="e.g. cms, blog">
|
|
</div>
|
|
<div class="field">
|
|
<label for="newKey">Key</label>
|
|
<input type="text" id="newKey" bind:value={newKey} placeholder="e.g. navigation.home">
|
|
</div>
|
|
<div class="field">
|
|
<label for="newValue">Value</label>
|
|
<input type="text" id="newValue" bind:value={newValue} placeholder="Translated text">
|
|
</div>
|
|
<div class="field">
|
|
<label for="saveBtn"> </label>
|
|
<button
|
|
type="button"
|
|
id="saveBtn"
|
|
class="ui fluid green button {loading ? 'loading' : ''}"
|
|
onclick={() => saveTranslation()}
|
|
disabled={!newKey || !newValue}
|
|
>
|
|
Add Override
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="column">
|
|
<table class="ui celled table">
|
|
<thead>
|
|
<tr>
|
|
<th>Group</th>
|
|
<th>Key</th>
|
|
<th>Value (Override)</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{#each items as item}
|
|
<tr>
|
|
<td class="collapsing">{item.group}</td>
|
|
<td class="collapsing"><code>{item.key}</code></td>
|
|
<td>
|
|
<div class="ui fluid input">
|
|
<input type="text" bind:value={item.value}>
|
|
</div>
|
|
</td>
|
|
<td class="collapsing">
|
|
<button
|
|
type="button"
|
|
class="ui blue icon button {loading ? 'loading' : ''}"
|
|
onclick={() => saveTranslation(item)}
|
|
title="Save"
|
|
>
|
|
<i class="save icon"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{/each}
|
|
{#if items.length === 0}
|
|
<tr>
|
|
<td colspan="4" class="center aligned">No overrides for this locale yet.</td>
|
|
</tr>
|
|
{/if}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|