Add a translation assistant to the panel
Each field's original sits beside the field to write, and a translation that fell behind shows what the original said when it was translated and what it says now, word by word. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -71,6 +71,69 @@ final class TranslationFreshness
|
||||
/**
|
||||
* @return array<string, CarbonInterface>
|
||||
*/
|
||||
/**
|
||||
* Field by field, for one language: which fields the original changed
|
||||
* after this language was last written, since when, and what the
|
||||
* original said back then — so a translator can see what to redo rather
|
||||
* than rereading the whole text.
|
||||
*
|
||||
* @return array<string, array{since: CarbonInterface, was: ?string}>
|
||||
*/
|
||||
public static function staleFields(Model $record, string $locale): array
|
||||
{
|
||||
$source = (string) config('locales.default');
|
||||
$fields = self::fields($record);
|
||||
$touched = self::lastTouched($record, $fields);
|
||||
$stale = [];
|
||||
|
||||
foreach ($fields as $field) {
|
||||
if ($locale === $source || blank($record->getTranslation($field, $locale, false))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sourceAt = $touched[$field][$source] ?? null;
|
||||
$translatedAt = $touched[$field][$locale] ?? $record->created_at;
|
||||
|
||||
if ($sourceAt !== null && $translatedAt !== null && $sourceAt->gt($translatedAt)) {
|
||||
$stale[$field] = [
|
||||
'since' => $sourceAt,
|
||||
'was' => self::sourceAsOf($record, $field, $translatedAt),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $stale;
|
||||
}
|
||||
|
||||
/**
|
||||
* The original's text in a field as it stood at a moment, from the
|
||||
* history: the last value written at or before it, or the value the first
|
||||
* later change replaced.
|
||||
*/
|
||||
protected static function sourceAsOf(Model $record, string $field, CarbonInterface $at): ?string
|
||||
{
|
||||
$source = (string) config('locales.default');
|
||||
$value = null;
|
||||
$found = false;
|
||||
|
||||
foreach ($record->revisions()->reorder()->orderBy('id')->get() as $revision) {
|
||||
$change = $revision->changeset[$field] ?? null;
|
||||
|
||||
if (! is_array($change)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($revision->created_at->lte($at)) {
|
||||
$value = ((array) ($change['new'] ?? []))[$source] ?? null;
|
||||
$found = true;
|
||||
} elseif (! $found) {
|
||||
return ((array) ($change['old'] ?? []))[$source] ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
return $found ? $value : $record->getTranslation($field, $source, false);
|
||||
}
|
||||
|
||||
protected static function compute(Model $record): array
|
||||
{
|
||||
$source = (string) config('locales.default');
|
||||
|
||||
Reference in New Issue
Block a user