Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Changes 13: New translation classes #6491

Merged
merged 23 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
52081a1
Add new Translation & Translations classes
bastianallgeier Jun 11, 2024
7955e19
Unit test setup for the Translations class
bastianallgeier Jun 12, 2024
022f1de
More unit tests and fixes
bastianallgeier Jun 12, 2024
ff85477
Add more unit tests for the Translations class
bastianallgeier Jun 14, 2024
3e13497
Move helper methods into TestCase class
bastianallgeier Jun 14, 2024
1fab8a0
Unit tests for the Translation class
bastianallgeier Jun 14, 2024
6ae1f2b
Don’t break Translation::content for now
bastianallgeier Jun 14, 2024
9aaa2a5
Fix ::slug and unit test
bastianallgeier Jun 14, 2024
cc3b59e
Add deprecation warnings
bastianallgeier Jun 14, 2024
a6f95e4
Fix class reference
bastianallgeier Jun 14, 2024
626936f
Fix the @coversDefaultClass annotation in the Translation class
bastianallgeier Jun 17, 2024
d910943
Fix the @coversDefaultClass annotation in the Translations class
bastianallgeier Jun 17, 2024
948f521
Replace usage of deprecated methods in unit tests
bastianallgeier Jun 17, 2024
241501d
Throw exception in Translations::findByKey if the language does not e…
bastianallgeier Jun 17, 2024
aaea8ee
Fix deprecation comments
bastianallgeier Jun 24, 2024
3bf5432
Add translation-methods key to the Helpers class
bastianallgeier Jun 24, 2024
5f1e539
Clean up Translations::load
bastianallgeier Jun 24, 2024
abe70ae
Improve deprecation warnings
bastianallgeier Jun 25, 2024
2e9767f
Use eventually cached content object
bastianallgeier Jun 25, 2024
deb295e
Don’t test slug in primary language
bastianallgeier Jun 25, 2024
bbade07
Add todo to Translation::create and Translations::create
bastianallgeier Jun 26, 2024
61c2e72
Fix deprecation warning
lukasbestle Jun 26, 2024
69a7632
Throw exceptions in deprecated Translation::parent and Translation::u…
bastianallgeier Jun 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/Cms/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ class Helpers
// TODO: switch to true in v6
'plugin-extends-root' => false,

// The `Content\Translation` class keeps a set of methods from the old
// `ContentTranslation` class for compatibility that should no longer be used.
// Some of them can be replaced by using `Version` class methods instead
// (see method comments). `Content\Translation::contentFile` should be avoided
// entirely and has no recommended replacement.
'translation-methods' => false,
bastianallgeier marked this conversation as resolved.
Show resolved Hide resolved

// Passing a single space as value to `Xml::attr()` has been
// deprecated. In a future version, passing a single space won't
// render an empty value anymore but a single space.
Expand Down
176 changes: 176 additions & 0 deletions src/Content/Translation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
<?php

namespace Kirby\Content;

use Kirby\Cms\Helpers;
use Kirby\Cms\Language;
use Kirby\Cms\ModelWithContent;

/**
* Each page, file or site can have multiple
* translated versions of their content,
* represented by this class
*
* @package Kirby Content
* @author Bastian Allgeier <[email protected]>
* @link https://getkirby.com
* @copyright Bastian Allgeier
* @license https://getkirby.com/license
*/
class Translation extends ContentTranslation
{
/**
* Creates a new translation object
*/
public function __construct(
protected ModelWithContent $model,
protected Version $version,
protected Language $language
) {
}

/**
* Improve `var_dump` output
* @codeCoverageIgnore
*/
public function __debugInfo(): array
{
return $this->toArray();
}

/**
* Returns the language code of the
* translation
*
* @deprecated 5.0.0 Use `::language()->code()` instead
*/
public function code(): string
{
Helpers::deprecated('`$translation->code()` has been deprecated. Use `$translation->language()->code()` instead.', 'translation-methods');
return $this->language->code();
}

/**
* Returns the translation content
* as plain array
*
* @deprecated 5.0.0 Use `::version()->content()->toArray()` instead
*/
public function content(): array
{
Helpers::deprecated('`$translation->content()` has been deprecated. Use `$translation->version()->content()` instead.', 'translation-methods');
bastianallgeier marked this conversation as resolved.
Show resolved Hide resolved
return $this->version->content($this->language)->toArray();
}

/**
* Absolute path to the translation content file
*
* @deprecated 5.0.0
*/
public function contentFile(): string
{
Helpers::deprecated('`$translation->contentFile()` has been deprecated. Use `$translation->version()->contentFile()` instead.', 'translation-methods');
bastianallgeier marked this conversation as resolved.
Show resolved Hide resolved
return $this->version->contentFile($this->language);
}

/**
* Creates a new Translation for the given model
*/
public static function create(
ModelWithContent $model,
Version $version,
Language $language,
array $fields,
string|null $slug = null
): static {
// add the custom slug to the fields array
if ($slug !== null) {
$fields['slug'] = $slug;
}

$version->create($fields, $language);

return new static(
model: $model,
version: $version,
language: $language,
);
}

/**
* Checks if the translation file exists
*
* @deprecated 5.0.0 Use `::version()->exists()` instead
*/
public function exists(): bool
{
Helpers::deprecated('`$translation->exists()` has been deprecated. Use `$translation->version()->exists()` instead.', 'translation-methods');
return $this->version->exists($this->language);
}

/**
* Returns the translation code as id
*/
public function id(): string
{
return $this->language->code();
}

/**
* Checks if the this is the default translation
* of the model
*
* @deprecated 5.0.0 Use `::language()->isDefault()` instead
*/
public function isDefault(): bool
{
Helpers::deprecated('`$translation->isDefault()` has been deprecated. Use `$translation->language()->isDefault()` instead.', 'translation-methods');
return $this->language->isDefault();
}

/**
* Returns the language
*/
public function language(): Language
{
return $this->language;
}

/**
* Returns the parent page, file or site object
*/
public function model(): ModelWithContent
{
return $this->model;
}

/**
* Returns the custom translation slug
*/
public function slug(): string|null
{
return $this->version->read($this->language)['slug'] ?? null;
bastianallgeier marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Converts the most important translation
* props to an array
*/
public function toArray(): array
{
return [
'code' => $this->language->code(),
'content' => $this->version->content($this->language)->toArray(),
'exists' => $this->version->exists($this->language),
'slug' => $this->slug(),
];
}

/**
* Returns the version
*/
public function version(): Version
{
return $this->version;
}
}
76 changes: 76 additions & 0 deletions src/Content/Translations.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

namespace Kirby\Content;

use Kirby\Cms\Collection;
use Kirby\Cms\Language;
use Kirby\Cms\Languages;
use Kirby\Cms\ModelWithContent;

/**
* @package Kirby Content
* @author Bastian Allgeier <[email protected]>
* @link https://getkirby.com
* @copyright Bastian Allgeier
* @license https://getkirby.com/license
*
* @extends \Kirby\Cms\Collection<\Kirby\Content\Translation>
*/
class Translations extends Collection
{
/**
* Creates a new Translations collection from
* an array of translations properties. This is
* used in LabPage::setTranslations to properly
* normalize an array definition.
*/
public static function create(
bastianallgeier marked this conversation as resolved.
Show resolved Hide resolved
ModelWithContent $model,
Version $version,
array $translations
): static {
foreach ($translations as $translation) {
Translation::create(
model: $model,
version: $version,
language: Language::ensure($translation['code'] ?? 'default'),
fields: $translation['content'] ?? [],
slug: $translation['slug'] ?? null
);
}

return static::load(
model: $model,
version: $version
);
}

/**
* Simplifies `Translations::find` by allowing to pass
* Language codes that will be properly validated here.
*/
public function findByKey(string $key): Translation|null
{
return parent::get(Language::ensure($key)->code());
}

/**
* Loads all available translations for a given model
*/
public static function load(
ModelWithContent $model,
Version $version
): static {
$translations = [];

foreach (Languages::ensure() as $language) {
$translations[] = new Translation(
model: $model,
version: $version,
language: $language
);
}

return new static($translations);
}
}
61 changes: 61 additions & 0 deletions tests/Content/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Kirby\Content;

use Kirby\Cms\App;
use Kirby\Data\Data;
use Kirby\Filesystem\Dir;
use Kirby\TestCase as BaseTestCase;

Expand All @@ -12,6 +13,66 @@ class TestCase extends BaseTestCase

protected $model;

public function assertContentFileExists(string|null $language = null, VersionId|null $versionId = null)
{
$this->assertFileExists($this->contentFile($language, $versionId));
}

public function assertContentFileDoesNotExist(string|null $language = null, VersionId|null $versionId = null)
{
$this->assertFileDoesNotExist($this->contentFile($language, $versionId));
}

public function contentFile(string|null $language = null, VersionId|null $versionId = null): string
{
return
$this->model->root() .
// add the changes folder
($versionId?->value() === 'changes' ? '/_changes/' : '/') .
// template
'article' .
// language code
($language === null ? '' : '.' . $language) .
'.txt';
}

public function createContentMultiLanguage(): array
{
Data::write($fileEN = $this->contentFile('en'), $contentEN = [
'title' => 'Title English',
'subtitle' => 'Subtitle English'
]);

Data::write($fileDE = $this->contentFile('de'), $contentDE = [
'title' => 'Title Deutsch',
'subtitle' => 'Subtitle Deutsch'
]);

return [
'en' => [
'content' => $contentEN,
'file' => $fileEN,
],
'de' => [
'content' => $contentDE,
'file' => $fileDE,
]
];
}

public function createContentSingleLanguage(): array
{
Data::write($file = $this->contentFile(), $content = [
'title' => 'Title',
'subtitle' => 'Subtitle'
]);

return [
'content' => $content,
'file' => $file
];
}

public function setUp(): void
{
Dir::make(static::TMP);
Expand Down
Loading
Loading