Forum tree model, i18n, and frontend updates
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
"symfony/runtime": "8.0.*",
|
||||
"symfony/security-bundle": "8.0.*",
|
||||
"symfony/serializer": "8.0.*",
|
||||
"symfony/translation": "8.0.*",
|
||||
"symfony/twig-bundle": "8.0.*",
|
||||
"symfony/validator": "8.0.*",
|
||||
"symfony/yaml": "8.0.*"
|
||||
|
||||
95
api/composer.lock
generated
95
api/composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "7c78a734d525250702b4a298784f81dd",
|
||||
"content-hash": "678b66a22585eb57ff21a981f084502f",
|
||||
"packages": [
|
||||
{
|
||||
"name": "api-platform/doctrine-common",
|
||||
@@ -6233,6 +6233,99 @@
|
||||
],
|
||||
"time": "2025-12-01T09:13:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation",
|
||||
"version": "v8.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation.git",
|
||||
"reference": "770e3b8b0ba8360958abedcabacd4203467333ca"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/770e3b8b0ba8360958abedcabacd4203467333ca",
|
||||
"reference": "770e3b8b0ba8360958abedcabacd4203467333ca",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.4",
|
||||
"symfony/polyfill-mbstring": "^1.0",
|
||||
"symfony/translation-contracts": "^3.6.1"
|
||||
},
|
||||
"conflict": {
|
||||
"nikic/php-parser": "<5.0",
|
||||
"symfony/http-client-contracts": "<2.5",
|
||||
"symfony/service-contracts": "<2.5"
|
||||
},
|
||||
"provide": {
|
||||
"symfony/translation-implementation": "2.3|3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"nikic/php-parser": "^5.0",
|
||||
"psr/log": "^1|^2|^3",
|
||||
"symfony/config": "^7.4|^8.0",
|
||||
"symfony/console": "^7.4|^8.0",
|
||||
"symfony/dependency-injection": "^7.4|^8.0",
|
||||
"symfony/finder": "^7.4|^8.0",
|
||||
"symfony/http-client-contracts": "^2.5|^3.0",
|
||||
"symfony/http-kernel": "^7.4|^8.0",
|
||||
"symfony/intl": "^7.4|^8.0",
|
||||
"symfony/polyfill-intl-icu": "^1.21",
|
||||
"symfony/routing": "^7.4|^8.0",
|
||||
"symfony/service-contracts": "^2.5|^3",
|
||||
"symfony/yaml": "^7.4|^8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"Resources/functions.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Translation\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Provides tools to internationalize your application",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/translation/tree/v8.0.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-12-01T09:13:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation-contracts",
|
||||
"version": "v3.6.1",
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
api_platform:
|
||||
title: speedBB API
|
||||
version: 1.0.0
|
||||
formats:
|
||||
json: ['application/json']
|
||||
jsonld: ['application/ld+json']
|
||||
defaults:
|
||||
stateless: true
|
||||
cache_headers:
|
||||
|
||||
5
api/config/packages/translation.yaml
Normal file
5
api/config/packages/translation.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
framework:
|
||||
default_locale: en
|
||||
translator:
|
||||
default_path: '%kernel.project_dir%/translations'
|
||||
providers:
|
||||
@@ -297,7 +297,7 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator;
|
||||
* },
|
||||
* },
|
||||
* translator?: bool|array{ // Translator configuration
|
||||
* enabled?: bool, // Default: false
|
||||
* enabled?: bool, // Default: true
|
||||
* fallbacks?: list<scalar|null>,
|
||||
* logging?: bool, // Default: false
|
||||
* formatter?: scalar|null, // Default: "translator.formatter.default"
|
||||
|
||||
24
api/migrations/Version20251224115331.php
Normal file
24
api/migrations/Version20251224115331.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
final class Version20251224115331 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Initial schema (executed previously).';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
}
|
||||
}
|
||||
46
api/migrations/Version20251224120510.php
Normal file
46
api/migrations/Version20251224120510.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20251224120510 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE TABLE forum (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(100) NOT NULL, description LONGTEXT DEFAULT NULL, type VARCHAR(20) NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, parent_id INT DEFAULT NULL, INDEX IDX_852BBECD727ACA70 (parent_id), PRIMARY KEY (id)) DEFAULT CHARACTER SET utf8mb4');
|
||||
$this->addSql('ALTER TABLE forum ADD CONSTRAINT FK_852BBECD727ACA70 FOREIGN KEY (parent_id) REFERENCES forum (id)');
|
||||
$this->addSql('ALTER TABLE thread DROP FOREIGN KEY `FK_31204C8312469DE2`');
|
||||
$this->addSql('DROP INDEX IDX_31204C8312469DE2 ON thread');
|
||||
$this->addSql('INSERT INTO forum (id, name, description, type, created_at, updated_at) SELECT id, name, description, \'forum\', created_at, updated_at FROM category');
|
||||
$this->addSql('ALTER TABLE thread CHANGE category_id forum_id INT NOT NULL');
|
||||
$this->addSql('ALTER TABLE thread ADD CONSTRAINT FK_31204C8329CCBAD0 FOREIGN KEY (forum_id) REFERENCES forum (id)');
|
||||
$this->addSql('CREATE INDEX IDX_31204C8329CCBAD0 ON thread (forum_id)');
|
||||
$this->addSql('DROP TABLE category');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE TABLE category (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(100) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_general_ci`, description LONGTEXT CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_general_ci`, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, PRIMARY KEY (id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_general_ci` ENGINE = InnoDB COMMENT = \'\' ');
|
||||
$this->addSql('ALTER TABLE forum DROP FOREIGN KEY FK_852BBECD727ACA70');
|
||||
$this->addSql('DROP TABLE forum');
|
||||
$this->addSql('ALTER TABLE thread DROP FOREIGN KEY FK_31204C8329CCBAD0');
|
||||
$this->addSql('DROP INDEX IDX_31204C8329CCBAD0 ON thread');
|
||||
$this->addSql('ALTER TABLE thread CHANGE forum_id category_id INT NOT NULL');
|
||||
$this->addSql('ALTER TABLE thread ADD CONSTRAINT `FK_31204C8312469DE2` FOREIGN KEY (category_id) REFERENCES category (id)');
|
||||
$this->addSql('CREATE INDEX IDX_31204C8312469DE2 ON thread (category_id)');
|
||||
}
|
||||
}
|
||||
11
api/public/.htaccess
Normal file
11
api/public/.htaccess
Normal file
@@ -0,0 +1,11 @@
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} -f
|
||||
RewriteRule ^ - [L]
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} -d
|
||||
RewriteRule ^ - [L]
|
||||
|
||||
RewriteRule ^ index.php [L]
|
||||
</IfModule>
|
||||
55
api/src/Controller/I18nController.php
Normal file
55
api/src/Controller/I18nController.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class I18nController
|
||||
{
|
||||
public function __construct(
|
||||
private TranslatorInterface $translator,
|
||||
#[Autowire('%kernel.default_locale%')]
|
||||
private string $defaultLocale
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route(
|
||||
'/api/i18n/{locale}',
|
||||
name: 'api_i18n',
|
||||
methods: ['GET'],
|
||||
requirements: ['locale' => '[A-Za-z0-9_-]+']
|
||||
)]
|
||||
public function __invoke(string $locale): JsonResponse
|
||||
{
|
||||
$messages = $this->getMessagesForLocale($locale);
|
||||
|
||||
if (!$messages && $locale !== $this->defaultLocale) {
|
||||
$messages = $this->getMessagesForLocale($this->defaultLocale);
|
||||
}
|
||||
|
||||
return new JsonResponse($messages);
|
||||
}
|
||||
|
||||
private function getMessagesForLocale(string $locale): array
|
||||
{
|
||||
$catalogue = $this->translator->getCatalogue($locale);
|
||||
$messages = $catalogue->all('messages');
|
||||
|
||||
$fallback = $catalogue->getFallbackCatalogue();
|
||||
while ($fallback) {
|
||||
foreach ($fallback->all('messages') as $key => $value) {
|
||||
if (!array_key_exists($key, $messages)) {
|
||||
$messages[$key] = $value;
|
||||
}
|
||||
}
|
||||
$fallback = $fallback->getFallbackCatalogue();
|
||||
}
|
||||
|
||||
ksort($messages);
|
||||
|
||||
return $messages;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use ApiPlatform\Doctrine\Orm\Filter\ExistsFilter;
|
||||
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
|
||||
use ApiPlatform\Metadata\ApiFilter;
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use ApiPlatform\Metadata\Delete;
|
||||
use ApiPlatform\Metadata\Get;
|
||||
@@ -16,48 +19,67 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
#[ORM\Entity]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ApiFilter(SearchFilter::class, properties: ['parent' => 'exact', 'type' => 'exact'])]
|
||||
#[ApiFilter(ExistsFilter::class, properties: ['parent'])]
|
||||
#[ApiResource(
|
||||
operations : [
|
||||
normalizationContext: ['groups' => ['forum:read']],
|
||||
denormalizationContext: ['groups' => ['forum:write']],
|
||||
operations: [
|
||||
new Get(),
|
||||
new GetCollection(),
|
||||
new Post(security: "is_granted('ROLE_ADMIN')"),
|
||||
new Patch(security: "is_granted('ROLE_ADMIN')"),
|
||||
new Delete(security: "is_granted('ROLE_ADMIN')")
|
||||
],
|
||||
normalizationContext : ['groups' => ['category:read']],
|
||||
denormalizationContext: ['groups' => ['category:write']]
|
||||
]
|
||||
)]
|
||||
class Category
|
||||
class Forum
|
||||
{
|
||||
public const TYPE_CATEGORY = 'category';
|
||||
public const TYPE_FORUM = 'forum';
|
||||
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
#[Groups(['category:read', 'thread:read'])]
|
||||
#[Groups(['forum:read', 'thread:read'])]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(length: 100)]
|
||||
#[Assert\NotBlank]
|
||||
#[Groups(['category:read', 'category:write', 'thread:read'])]
|
||||
#[Groups(['forum:read', 'forum:write', 'thread:read'])]
|
||||
private ?string $name = null;
|
||||
|
||||
#[ORM\Column(type: 'text', nullable: true)]
|
||||
#[Groups(['category:read', 'category:write'])]
|
||||
#[Groups(['forum:read', 'forum:write'])]
|
||||
private ?string $description = null;
|
||||
|
||||
#[ORM\Column(length: 20)]
|
||||
#[Assert\Choice(choices: [self::TYPE_CATEGORY, self::TYPE_FORUM])]
|
||||
#[Groups(['forum:read', 'forum:write'])]
|
||||
private string $type = self::TYPE_CATEGORY;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
|
||||
#[Groups(['forum:read', 'forum:write'])]
|
||||
private ?self $parent = null;
|
||||
|
||||
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)]
|
||||
#[Groups(['forum:read'])]
|
||||
private Collection $children;
|
||||
|
||||
#[ORM\OneToMany(mappedBy: 'forum', targetEntity: Thread::class)]
|
||||
#[Groups(['forum:read'])]
|
||||
private Collection $threads;
|
||||
|
||||
#[ORM\Column]
|
||||
#[Groups(['category:read'])]
|
||||
#[Groups(['forum:read'])]
|
||||
private ?\DateTimeImmutable $createdAt = null;
|
||||
|
||||
#[ORM\Column]
|
||||
#[Groups(['category:read'])]
|
||||
#[Groups(['forum:read'])]
|
||||
private ?\DateTimeImmutable $updatedAt = null;
|
||||
|
||||
#[ORM\OneToMany(mappedBy: 'category', targetEntity: Thread::class)]
|
||||
#[Groups(['category:read'])]
|
||||
private Collection $threads;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->children = new ArrayCollection();
|
||||
$this->threads = new ArrayCollection();
|
||||
}
|
||||
|
||||
@@ -104,14 +126,36 @@ class Category
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): ?\DateTimeImmutable
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->createdAt;
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): ?\DateTimeImmutable
|
||||
public function setType(string $type): self
|
||||
{
|
||||
return $this->updatedAt;
|
||||
$this->type = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getParent(): ?self
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
public function setParent(?self $parent): self
|
||||
{
|
||||
$this->parent = $parent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, Forum>
|
||||
*/
|
||||
public function getChildren(): Collection
|
||||
{
|
||||
return $this->children;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,4 +165,14 @@ class Category
|
||||
{
|
||||
return $this->threads;
|
||||
}
|
||||
|
||||
public function isCategory(): bool
|
||||
{
|
||||
return $this->type === self::TYPE_CATEGORY;
|
||||
}
|
||||
|
||||
public function isForum(): bool
|
||||
{
|
||||
return $this->type === self::TYPE_FORUM;
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ use ApiPlatform\Metadata\Delete;
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use ApiPlatform\Metadata\GetCollection;
|
||||
use ApiPlatform\Metadata\Patch;
|
||||
use ApiPlatform\Metadata\Post;
|
||||
use ApiPlatform\Metadata\Post as PostOperation;
|
||||
use App\State\ThreadOwnerProcessor;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
@@ -19,14 +19,14 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
#[ORM\Entity]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ApiFilter(SearchFilter::class, properties: ['category' => 'exact'])]
|
||||
#[ApiFilter(SearchFilter::class, properties: ['forum' => 'exact'])]
|
||||
#[ApiResource(
|
||||
normalizationContext: ['groups' => ['thread:read']],
|
||||
denormalizationContext: ['groups' => ['thread:write']],
|
||||
operations: [
|
||||
new Get(),
|
||||
new GetCollection(),
|
||||
new Post(
|
||||
new PostOperation(
|
||||
security: "is_granted('ROLE_USER')",
|
||||
processor: ThreadOwnerProcessor::class
|
||||
),
|
||||
@@ -39,12 +39,12 @@ class Thread
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
#[Groups(['thread:read', 'category:read', 'post:read'])]
|
||||
#[Groups(['thread:read', 'forum:read', 'post:read'])]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(length: 200)]
|
||||
#[Assert\NotBlank]
|
||||
#[Groups(['thread:read', 'thread:write', 'category:read', 'post:read'])]
|
||||
#[Groups(['thread:read', 'thread:write', 'forum:read', 'post:read'])]
|
||||
private ?string $title = null;
|
||||
|
||||
#[ORM\Column(type: 'text')]
|
||||
@@ -52,11 +52,12 @@ class Thread
|
||||
#[Groups(['thread:read', 'thread:write'])]
|
||||
private ?string $body = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Category::class, inversedBy: 'threads')]
|
||||
#[ORM\ManyToOne(targetEntity: Forum::class, inversedBy: 'threads')]
|
||||
#[ORM\JoinColumn(nullable: false)]
|
||||
#[Assert\NotNull]
|
||||
#[Assert\Expression("this.getForum() and this.getForum().isForum()", message: "Thread must belong to a forum.")]
|
||||
#[Groups(['thread:read', 'thread:write'])]
|
||||
private ?Category $category = null;
|
||||
private ?Forum $forum = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'threads')]
|
||||
#[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')]
|
||||
@@ -123,14 +124,14 @@ class Thread
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCategory(): ?Category
|
||||
public function getForum(): ?Forum
|
||||
{
|
||||
return $this->category;
|
||||
return $this->forum;
|
||||
}
|
||||
|
||||
public function setCategory(?Category $category): self
|
||||
public function setForum(?Forum $forum): self
|
||||
{
|
||||
$this->category = $category;
|
||||
$this->forum = $forum;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ use ApiPlatform\Metadata\Delete;
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use ApiPlatform\Metadata\GetCollection;
|
||||
use ApiPlatform\Metadata\Patch;
|
||||
use ApiPlatform\Metadata\Post;
|
||||
use ApiPlatform\Metadata\Post as PostOperation;
|
||||
use App\State\UserPasswordHasherProcessor;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
@@ -29,7 +29,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
operations: [
|
||||
new Get(security: "is_granted('ROLE_ADMIN')"),
|
||||
new GetCollection(security: "is_granted('ROLE_ADMIN')"),
|
||||
new Post(
|
||||
new PostOperation(
|
||||
security: "is_granted('PUBLIC_ACCESS')",
|
||||
processor: UserPasswordHasherProcessor::class,
|
||||
validationContext: ['groups' => ['Default', 'user:create']]
|
||||
|
||||
@@ -144,6 +144,19 @@
|
||||
"config/routes/security.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/translation": {
|
||||
"version": "8.0",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "6.3",
|
||||
"ref": "620a1b84865ceb2ba304c8f8bf2a185fbf32a843"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/translation.yaml",
|
||||
"translations/.gitignore"
|
||||
]
|
||||
},
|
||||
"symfony/twig-bundle": {
|
||||
"version": "8.0",
|
||||
"recipe": {
|
||||
|
||||
0
api/translations/.gitignore
vendored
Normal file
0
api/translations/.gitignore
vendored
Normal file
166
api/translations/messages.de.po
Normal file
166
api/translations/messages.de.po
Normal file
@@ -0,0 +1,166 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Language: de\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
|
||||
msgid "app.brand"
|
||||
msgstr "speedBB"
|
||||
|
||||
msgid "nav.forums"
|
||||
msgstr "Foren"
|
||||
|
||||
msgid "nav.login"
|
||||
msgstr "Anmelden"
|
||||
|
||||
msgid "nav.register"
|
||||
msgstr "Registrieren"
|
||||
|
||||
msgid "nav.logout"
|
||||
msgstr "Abmelden"
|
||||
|
||||
msgid "nav.language"
|
||||
msgstr "Sprache"
|
||||
|
||||
msgid "home.hero_title"
|
||||
msgstr "Foren"
|
||||
|
||||
msgid "home.hero_body"
|
||||
msgstr "Entdecke Diskussionen, stelle Fragen und teile Ideen in Kategorien und Foren."
|
||||
|
||||
msgid "home.browse"
|
||||
msgstr "Foren durchsuchen"
|
||||
|
||||
msgid "home.loading"
|
||||
msgstr "Foren werden geladen..."
|
||||
|
||||
msgid "home.empty"
|
||||
msgstr "Noch keine Foren vorhanden. Lege das erste Forum in der API an."
|
||||
|
||||
msgid "forum.threads"
|
||||
msgstr "Threads"
|
||||
|
||||
msgid "forum.start_thread"
|
||||
msgstr "Thread starten"
|
||||
|
||||
msgid "forum.loading"
|
||||
msgstr "Forum wird geladen..."
|
||||
|
||||
msgid "forum.type_category"
|
||||
msgstr "Kategorie"
|
||||
|
||||
msgid "forum.type_forum"
|
||||
msgstr "Forum"
|
||||
|
||||
msgid "forum.no_description"
|
||||
msgstr "Noch keine Beschreibung vorhanden."
|
||||
|
||||
msgid "forum.empty_threads"
|
||||
msgstr "Noch keine Threads vorhanden. Starte unten einen."
|
||||
|
||||
msgid "forum.login_hint"
|
||||
msgstr "Melde dich an, um einen neuen Thread zu erstellen."
|
||||
|
||||
msgid "forum.open"
|
||||
msgstr "Forum öffnen"
|
||||
|
||||
msgid "forum.children"
|
||||
msgstr "Unterforen"
|
||||
|
||||
msgid "forum.empty_children"
|
||||
msgstr "Noch keine Unterforen vorhanden."
|
||||
|
||||
msgid "forum.only_forums"
|
||||
msgstr "Threads können nur in Foren erstellt werden."
|
||||
|
||||
msgid "thread.replies"
|
||||
msgstr "Antworten"
|
||||
|
||||
msgid "thread.reply"
|
||||
msgstr "Antworten"
|
||||
|
||||
msgid "thread.loading"
|
||||
msgstr "Thread wird geladen..."
|
||||
|
||||
msgid "thread.label"
|
||||
msgstr "Thread"
|
||||
|
||||
msgid "thread.category"
|
||||
msgstr "Forum:"
|
||||
|
||||
msgid "thread.back_to_category"
|
||||
msgstr "Zurück zum Forum"
|
||||
|
||||
msgid "thread.empty"
|
||||
msgstr "Sei die erste Person, die antwortet."
|
||||
|
||||
msgid "thread.anonymous"
|
||||
msgstr "Anonym"
|
||||
|
||||
msgid "thread.login_hint"
|
||||
msgstr "Melde dich an, um auf diesen Thread zu antworten."
|
||||
|
||||
msgid "thread.view"
|
||||
msgstr "Thread ansehen"
|
||||
|
||||
msgid "auth.login_title"
|
||||
msgstr "Anmelden"
|
||||
|
||||
msgid "auth.login_hint"
|
||||
msgstr "Melde dich an, um neue Threads zu starten und zu antworten."
|
||||
|
||||
msgid "auth.register_title"
|
||||
msgstr "Konto erstellen"
|
||||
|
||||
msgid "auth.register_hint"
|
||||
msgstr "Registriere dich mit E-Mail und einem eindeutigen Benutzernamen."
|
||||
|
||||
msgid "footer.copy"
|
||||
msgstr "speedBB Forum. Powered by API Platform und React-Bootstrap."
|
||||
|
||||
msgid "form.title"
|
||||
msgstr "Titel"
|
||||
|
||||
msgid "form.body"
|
||||
msgstr "Inhalt"
|
||||
|
||||
msgid "form.message"
|
||||
msgstr "Nachricht"
|
||||
|
||||
msgid "form.email"
|
||||
msgstr "E-Mail"
|
||||
|
||||
msgid "form.username"
|
||||
msgstr "Benutzername"
|
||||
|
||||
msgid "form.password"
|
||||
msgstr "Passwort"
|
||||
|
||||
msgid "form.thread_title_placeholder"
|
||||
msgstr "Thema"
|
||||
|
||||
msgid "form.thread_body_placeholder"
|
||||
msgstr "Teile den Kontext und deine Frage."
|
||||
|
||||
msgid "form.reply_placeholder"
|
||||
msgstr "Schreibe deine Antwort."
|
||||
|
||||
msgid "form.posting"
|
||||
msgstr "Wird gesendet..."
|
||||
|
||||
msgid "form.create_thread"
|
||||
msgstr "Thread erstellen"
|
||||
|
||||
msgid "form.post_reply"
|
||||
msgstr "Antwort posten"
|
||||
|
||||
msgid "form.signing_in"
|
||||
msgstr "Anmeldung läuft..."
|
||||
|
||||
msgid "form.sign_in"
|
||||
msgstr "Anmelden"
|
||||
|
||||
msgid "form.registering"
|
||||
msgstr "Registrierung läuft..."
|
||||
|
||||
msgid "form.create_account"
|
||||
msgstr "Konto erstellen"
|
||||
166
api/translations/messages.en.po
Normal file
166
api/translations/messages.en.po
Normal file
@@ -0,0 +1,166 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Language: en\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
|
||||
msgid "app.brand"
|
||||
msgstr "speedBB"
|
||||
|
||||
msgid "nav.forums"
|
||||
msgstr "Forums"
|
||||
|
||||
msgid "nav.login"
|
||||
msgstr "Login"
|
||||
|
||||
msgid "nav.register"
|
||||
msgstr "Register"
|
||||
|
||||
msgid "nav.logout"
|
||||
msgstr "Logout"
|
||||
|
||||
msgid "nav.language"
|
||||
msgstr "Language"
|
||||
|
||||
msgid "home.hero_title"
|
||||
msgstr "Forums"
|
||||
|
||||
msgid "home.hero_body"
|
||||
msgstr "Explore conversations, ask questions, and share ideas across categories and forums."
|
||||
|
||||
msgid "home.browse"
|
||||
msgstr "Browse forums"
|
||||
|
||||
msgid "home.loading"
|
||||
msgstr "Loading forums..."
|
||||
|
||||
msgid "home.empty"
|
||||
msgstr "No forums yet. Create the first one in the API."
|
||||
|
||||
msgid "forum.threads"
|
||||
msgstr "Threads"
|
||||
|
||||
msgid "forum.start_thread"
|
||||
msgstr "Start a thread"
|
||||
|
||||
msgid "forum.loading"
|
||||
msgstr "Loading forum..."
|
||||
|
||||
msgid "forum.type_category"
|
||||
msgstr "Category"
|
||||
|
||||
msgid "forum.type_forum"
|
||||
msgstr "Forum"
|
||||
|
||||
msgid "forum.no_description"
|
||||
msgstr "No description added yet."
|
||||
|
||||
msgid "forum.empty_threads"
|
||||
msgstr "No threads here yet. Start one below."
|
||||
|
||||
msgid "forum.login_hint"
|
||||
msgstr "Log in to create a new thread."
|
||||
|
||||
msgid "forum.open"
|
||||
msgstr "Open forum"
|
||||
|
||||
msgid "forum.children"
|
||||
msgstr "Sub-forums"
|
||||
|
||||
msgid "forum.empty_children"
|
||||
msgstr "No sub-forums yet."
|
||||
|
||||
msgid "forum.only_forums"
|
||||
msgstr "Threads can only be created in forums."
|
||||
|
||||
msgid "thread.replies"
|
||||
msgstr "Replies"
|
||||
|
||||
msgid "thread.reply"
|
||||
msgstr "Reply"
|
||||
|
||||
msgid "thread.loading"
|
||||
msgstr "Loading thread..."
|
||||
|
||||
msgid "thread.label"
|
||||
msgstr "Thread"
|
||||
|
||||
msgid "thread.category"
|
||||
msgstr "Forum:"
|
||||
|
||||
msgid "thread.back_to_category"
|
||||
msgstr "Back to forum"
|
||||
|
||||
msgid "thread.empty"
|
||||
msgstr "Be the first to reply."
|
||||
|
||||
msgid "thread.anonymous"
|
||||
msgstr "Anonymous"
|
||||
|
||||
msgid "thread.login_hint"
|
||||
msgstr "Log in to reply to this thread."
|
||||
|
||||
msgid "thread.view"
|
||||
msgstr "View thread"
|
||||
|
||||
msgid "auth.login_title"
|
||||
msgstr "Log in"
|
||||
|
||||
msgid "auth.login_hint"
|
||||
msgstr "Access your account to start new threads and reply."
|
||||
|
||||
msgid "auth.register_title"
|
||||
msgstr "Create account"
|
||||
|
||||
msgid "auth.register_hint"
|
||||
msgstr "Register with an email and a unique username."
|
||||
|
||||
msgid "footer.copy"
|
||||
msgstr "speedBB forum. Powered by API Platform and React-Bootstrap."
|
||||
|
||||
msgid "form.title"
|
||||
msgstr "Title"
|
||||
|
||||
msgid "form.body"
|
||||
msgstr "Body"
|
||||
|
||||
msgid "form.message"
|
||||
msgstr "Message"
|
||||
|
||||
msgid "form.email"
|
||||
msgstr "Email"
|
||||
|
||||
msgid "form.username"
|
||||
msgstr "Username"
|
||||
|
||||
msgid "form.password"
|
||||
msgstr "Password"
|
||||
|
||||
msgid "form.thread_title_placeholder"
|
||||
msgstr "Topic headline"
|
||||
|
||||
msgid "form.thread_body_placeholder"
|
||||
msgstr "Share the context and your question."
|
||||
|
||||
msgid "form.reply_placeholder"
|
||||
msgstr "Share your reply."
|
||||
|
||||
msgid "form.posting"
|
||||
msgstr "Posting..."
|
||||
|
||||
msgid "form.create_thread"
|
||||
msgstr "Create thread"
|
||||
|
||||
msgid "form.post_reply"
|
||||
msgstr "Post reply"
|
||||
|
||||
msgid "form.signing_in"
|
||||
msgstr "Signing in..."
|
||||
|
||||
msgid "form.sign_in"
|
||||
msgstr "Sign in"
|
||||
|
||||
msgid "form.registering"
|
||||
msgstr "Registering..."
|
||||
|
||||
msgid "form.create_account"
|
||||
msgstr "Create account"
|
||||
Reference in New Issue
Block a user