Skip to content

Commit 57f1965

Browse files
committed
restructure translations in tags
1 parent ffc5aa9 commit 57f1965

7 files changed

Lines changed: 181 additions & 322 deletions

File tree

packages/tag/src/Models/Tag.php

Lines changed: 106 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -39,97 +39,9 @@ class Tag extends Model implements HasMedia, TranslatableContract
3939
'count' => 'integer',
4040
];
4141

42-
/**
43-
* Handle filling translations from form data
44-
*/
45-
public function fillTranslations(array $translations): self
46-
{
47-
foreach ($translations as $locale => $data) {
48-
if (! empty($data['title'])) {
49-
// Get the translation for this locale (or create a new one)
50-
$translation = $this->translateOrNew($locale);
51-
52-
// Check if title has changed
53-
if ($translation->title !== $data['title']) {
54-
$translation->title = $data['title'];
55-
}
56-
57-
// Handle the slug only if it has changed
58-
$slug = $data['slug'] ?? Str::slug($data['title']);
59-
if ($translation->slug !== $slug) {
60-
$slug = $this->generateUniqueSlug($slug, $locale);
61-
$translation->slug = $slug;
62-
}
63-
64-
// Handle content only if it has changed
65-
if ($translation->content !== ($data['content'] ?? null)) {
66-
$translation->content = $data['content'] ?? null;
67-
}
68-
69-
$translation->save();
70-
}
71-
}
72-
73-
return $this;
74-
}
75-
76-
public function generateUniqueSlug(string $slug, string $locale, int $counter = 0): string
77-
{
78-
// Append counter if needed
79-
$uniqueSlug = $counter > 0 ? "{$slug}-{$counter}" : $slug;
80-
81-
// Check if the slug exists for this locale
82-
$exists = static::whereHas('translations', function ($query) use ($uniqueSlug, $locale) {
83-
$query->where('slug', $uniqueSlug)->where('locale', $locale);
84-
})->exists();
85-
86-
// If exists, try again with an incremented counter
87-
return $exists ? $this->generateUniqueSlug($slug, $locale, $counter + 1) : $uniqueSlug;
88-
}
8942

90-
/**
91-
* Get all translations as a formatted array
92-
*/
93-
public function getTranslationsArray(): array
94-
{
95-
$translations = [];
96-
97-
foreach ($this->translations as $translation) {
98-
$translations[$translation->locale] = [
99-
'title' => $translation->title,
100-
'slug' => $translation->slug,
101-
'content' => $translation->content,
102-
];
103-
}
10443

105-
return $translations;
106-
}
10744

108-
/**
109-
* Create a new tag with translations
110-
*/
111-
public static function createWithTranslations(array $attributes, array $translations): self
112-
{
113-
$tag = new static;
114-
$tag->fill($attributes);
115-
$tag->save();
116-
117-
$tag->fillTranslations($translations)->save();
118-
119-
return $tag;
120-
}
121-
122-
/**
123-
* Update tag with translations
124-
*/
125-
public function updateWithTranslations(array $attributes, array $translations): self
126-
{
127-
$this->fill($attributes);
128-
$this->fillTranslations($translations);
129-
$this->save();
130-
131-
return $this;
132-
}
13345

13446
protected static function newFactory(): TagFactory
13547
{
@@ -176,4 +88,110 @@ public function mediaThroughUsables()
17688
'media_id'
17789
)->where('media_usables.media_usable_type', '=', static::class);
17890
}
91+
92+
public function getAttribute($key)
93+
{
94+
if (in_array($key, $this->translatedAttributes)) {
95+
$lang = request()->query('lang') ?? app()->getLocale();
96+
97+
return $this->translate($lang, false) ? $this->translate($lang, false)->$key : null;
98+
}
99+
100+
return parent::getAttribute($key);
101+
}
102+
103+
public function setAttribute($key, $value)
104+
{
105+
if (in_array($key, $this->translatedAttributes)) {
106+
$lang = request()->query('lang') ?? app()->getLocale();
107+
108+
$this->translateOrNew($lang)->$key = $value;
109+
110+
return $this;
111+
}
112+
113+
return parent::setAttribute($key, $value);
114+
}
115+
116+
/**
117+
* Helper to get translated value
118+
*/
119+
protected function getTranslated($key, $locale)
120+
{
121+
// First try to get from loaded translations
122+
if ($this->relationLoaded('translations')) {
123+
$translation = $this->translations
124+
->where('locale', $locale)
125+
->first();
126+
127+
if ($translation) {
128+
return $translation->$key;
129+
}
130+
}
131+
132+
// Fallback to direct translation lookup
133+
$translation = $this->translate($locale);
134+
135+
return $translation ? $translation->$key : '';
136+
}
137+
138+
/**
139+
* Override toArray to include translations
140+
*/
141+
public function toArray()
142+
{
143+
$attributes = parent::toArray();
144+
145+
if ($locale = request()->query('lang')) {
146+
foreach ($this->translatedAttributes as $attr) {
147+
$attributes[$attr] = $this->getTranslated($attr, $locale);
148+
}
149+
}
150+
151+
return $attributes;
152+
}
153+
154+
/**
155+
* Get all available translations for this model
156+
*/
157+
public function getAvailableTranslations(): array
158+
{
159+
return $this->translations->pluck('locale')->toArray();
160+
}
161+
162+
/**
163+
* Check if a translation exists for a specific locale
164+
*/
165+
public function hasTranslation(?string $locale = null): bool
166+
{
167+
if ($locale === null) {
168+
$locale = request()->query('lang') ?? app()->getLocale();
169+
}
170+
171+
return $this->translations->contains('locale', $locale);
172+
}
173+
174+
/**
175+
* Create a new translation for a specific locale
176+
*/
177+
public function createTranslation(string $locale, array $attributes = []): void
178+
{
179+
$translation = $this->translateOrNew($locale);
180+
181+
foreach ($attributes as $key => $value) {
182+
if (in_array($key, $this->translatedAttributes)) {
183+
$translation->$key = $value;
184+
}
185+
}
186+
187+
$this->translations()->save($translation);
188+
}
189+
190+
/**
191+
* Delete a translation for a specific locale
192+
*/
193+
public function deleteTranslation(string $locale): bool
194+
{
195+
return $this->translations()->where('locale', $locale)->delete();
196+
}
179197
}

packages/tag/src/Models/TagTranslation.php

Lines changed: 1 addition & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class TagTranslation extends Model
1010
{
1111
public $timestamps = false;
1212

13-
protected $fillable = ['title', 'slug', 'content'];
13+
protected $fillable = ['locale', 'tag_id', 'title', 'slug', 'content'];
1414

1515
/**
1616
* The attributes that should be cast.
@@ -23,48 +23,5 @@ class TagTranslation extends Model
2323
'content' => 'string',
2424
];
2525

26-
protected static function boot()
27-
{
28-
parent::boot();
2926

30-
static::saving(function (self $translation) {
31-
// Generate slug from title if not provided
32-
if (empty($translation->slug) && ! empty($translation->title)) {
33-
$translation->slug = Str::slug($translation->title);
34-
}
35-
36-
// Ensure slug uniqueness within the same locale
37-
if ($translation->isDirty('slug')) {
38-
$exists = static::where('locale', $translation->locale)
39-
->where('slug', $translation->slug)
40-
->where('id', '!=', $translation->id ?? 0)
41-
->exists();
42-
43-
if ($exists) {
44-
throw ValidationException::withMessages([
45-
'slug' => ["The slug '{$translation->slug}' already exists for locale '{$translation->locale}'."],
46-
]);
47-
}
48-
}
49-
});
50-
}
51-
52-
/**
53-
* Generate a unique slug for the translation
54-
*/
55-
public static function generateUniqueSlug(string $title, string $locale, ?int $excludeId = null): string
56-
{
57-
$slug = Str::slug($title);
58-
$originalSlug = $slug;
59-
$counter = 1;
60-
61-
while (static::where('locale', $locale)
62-
->where('slug', $slug)
63-
->when($excludeId, fn ($query) => $query->where('id', '!=', $excludeId))
64-
->exists()) {
65-
$slug = $originalSlug.'-'.$counter++;
66-
}
67-
68-
return $slug;
69-
}
7027
}

0 commit comments

Comments
 (0)