Skip to content

Commit

Permalink
Add internationalization for error messages and static pages
Browse files Browse the repository at this point in the history
The changes include internationalization for error messages and static pages URL. New Symfony translation files for error pages and time validation have been added. The language is now automatically set from the HTTP Accept-Language header. ItemController includes a new function 'addItem' to handle item creation.
  • Loading branch information
Spomky committed Apr 29, 2024
1 parent d7e14c8 commit cdaf355
Show file tree
Hide file tree
Showing 20 changed files with 757 additions and 139 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,10 @@
/public/assets/
/assets/vendor/
###< symfony/asset-mapper ###

/public/favicon.ico
/public/favicons
/public/workbox
/public/site.webmanifest
/public/site.*.webmanifest
/public/sw.js
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

# Symfony + PWA = 💕

## Introduction
Expand Down
196 changes: 109 additions & 87 deletions composer.lock

Large diffs are not rendered by default.

21 changes: 15 additions & 6 deletions config/packages/pwa.yaml
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
pwa:
image_processor: 'pwa.image_processor.imagick'
# user_agent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'
favicons:
enabled: true
src: "images/todo.svg"
tile_color: "#c026d3"
manifest:
enabled: true
public_url: '/site.{locale}.webmanifest'
background_color: "#c026d3"
theme_color: "#c026d3"
name: 'Simple TODO App'
short_name: 'Todo App'
description: 'A simple TODO application build using Symfony and PHPWA'
name: 'app.name'
short_name: 'app.short_name'
description: 'app.description'
orientation: "any"
display: "standalone"
scope: "/"
display_override: ['fullscreen', 'minimal-ui', 'window-controls-overlay']
id: "/"
start_url: "/"
start_url: "app.start_url"
icons:
- src: "images/todo.svg"
sizes: "any"
Expand All @@ -37,7 +43,7 @@ pwa:
max_age: 60
max_entries: 30
preload_urls:
- '@homepage'
- '@static_pages'
strategy: 'NetworkFirst'
broadcast: true
range_requests: true
Expand All @@ -51,7 +57,10 @@ pwa:
- 'api_entrypoint'
- '_api_/items{._format}_get_collection'
offline_fallback:
page: 'app_homepage'
page:
path: 'app_homepage'
params:
_locale: 'en_US'
background_sync:
- queue_name: 'items'
match_callback: 'startsWith: /items/'
Expand Down
9 changes: 6 additions & 3 deletions config/packages/translation.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
framework:
default_locale: en
set_locale_from_accept_language: true
set_content_language_from_locale: true
enabled_locales: '%app.supported_locales%'
default_locale: '%app.default_locale%'
translator:
default_path: '%kernel.project_dir%/translations'
fallbacks:
- en
providers:
- en_US
providers: ~
7 changes: 7 additions & 0 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
parameters:
locale: 'en-US'
app.default_locale: 'en-US'
app.supported_locales: ['en_US', 'fr_FR']
app.supported_locales_regex: 'en_US|fr_FR'

services:
# default configuration for services in *this* file
Expand All @@ -22,3 +26,6 @@ services:

# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones

App\PreloadGenerator\StaticPagesUrlPreloadGenerator:
tags: ['spomky_labs_pwa.preload_urls_generator']
Binary file removed public/favicon.ico
Binary file not shown.
43 changes: 1 addition & 42 deletions src/Controller/HomepageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,15 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use SpomkyLabs\PwaBundle\Attribute\PreloadUrl;

#[Route('/{_locale<%app.supported_locales_regex%>}')]
class HomepageController extends AbstractController
{
public function __construct(
private readonly ItemHandler $itemHandler,
private readonly ItemRepository $itemRepository,
){}

#[PreloadUrl(alias: 'homepage', params: ['_locale' => 'fr'])]
#[PreloadUrl(alias: 'homepage', params: ['_locale' => 'en'])]
#[PreloadUrl(alias: 'homepage', params: ['_locale' => 'it'])]
#[Route('/', name: 'app_homepage', methods: [Request::METHOD_GET])]
public function homepage(): Response
{
Expand All @@ -34,42 +31,4 @@ public function homepage(): Response

return $response;
}

#[Route('/add', name: 'app_add_item', methods: [Request::METHOD_POST])]
public function addItem(Request $request): Response
{
$form = $this->itemHandler->prepare();
$item = $this->itemHandler->handle($form, $request);
if ($item !== null) {
$this->addFlash('success', 'Item added');
return $this->redirectToRoute('app_homepage');
}
$this->addFlash('error', 'Item not added');
return $this->redirectToRoute('app_homepage');
}

#[Route('/items/{id}/toggle', name: 'app_toggle', methods: [Request::METHOD_POST])]
public function toggle(string $id): Response
{
$item = $this->itemRepository->findOneById($id);
if ($item !== null) {
$item->toggle();
$this->itemRepository->save($item);
}
$this->addFlash('success', 'Item state changed');

return $this->redirectToRoute('app_homepage');
}

#[Route('/items/{id}/remove', name: 'app_remove', methods: [Request::METHOD_POST])]
public function remove(string $id): Response
{
$item = $this->itemRepository->findOneById($id);
if ($item !== null) {
$this->itemRepository->remove($item);
}
$this->addFlash('success', 'Item removed');

return $this->redirectToRoute('app_homepage');
}
}
56 changes: 56 additions & 0 deletions src/Controller/ItemController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

namespace App\Controller;

use App\Form\ItemHandler;
use App\Repository\ItemRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

class ItemController extends AbstractController
{
public function __construct(
private readonly ItemHandler $itemHandler,
private readonly ItemRepository $itemRepository,
){}

#[Route('/add', name: 'app_add_item', methods: [Request::METHOD_POST])]
public function addItem(Request $request): Response
{
$form = $this->itemHandler->prepare();
$item = $this->itemHandler->handle($form, $request);
if ($item !== null) {
$this->addFlash('success', 'Item added');
return $this->redirectToRoute('app_homepage');
}
$this->addFlash('error', 'Item not added');
return $this->redirectToRoute('app_homepage');
}

#[Route('/items/{id}/toggle', name: 'app_toggle', methods: [Request::METHOD_POST])]
public function toggle(string $id): Response
{
$item = $this->itemRepository->findOneById($id);
if ($item !== null) {
$item->toggle();
$this->itemRepository->save($item);
}
$this->addFlash('success', 'Item state changed');

return $this->redirectToRoute('app_homepage');
}

#[Route('/items/{id}/remove', name: 'app_remove', methods: [Request::METHOD_POST])]
public function remove(string $id): Response
{
$item = $this->itemRepository->findOneById($id);
if ($item !== null) {
$this->itemRepository->remove($item);
}
$this->addFlash('success', 'Item removed');

return $this->redirectToRoute('app_homepage');
}
}
38 changes: 38 additions & 0 deletions src/Controller/RootController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

final class RootController extends AbstractController
{
public function __construct(
#[Autowire(param: 'app.default_locale')]
private readonly string $defaultLocale,
#[Autowire(param: 'app.supported_locales')]
private readonly array $supportedLocales,
) {
}

#[Route('/', name: 'app_root', methods: [Request::METHOD_GET])]
public function __invoke(Request $request): Response
{
$locale =
$request->attributes->get('_locale') ??
$request->getSession()
->get('_locale') ??
$request->getPreferredLanguage($this->supportedLocales) ??
$this->defaultLocale
;

return $this->redirectToRoute('app_homepage', [
'_locale' => $locale,
], Response::HTTP_SEE_OTHER);
}
}
36 changes: 36 additions & 0 deletions src/PreloadGenerator/StaticPagesUrlPreloadGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace App\PreloadGenerator;

use SpomkyLabs\PwaBundle\CachingStrategy\PreloadUrlsGeneratorInterface;
use SpomkyLabs\PwaBundle\Dto\Url;
use SpomkyLabs\PwaBundle\Dto\Manifest;
use Symfony\Component\DependencyInjection\Attribute\Autowire;

final readonly class StaticPagesUrlPreloadGenerator implements PreloadUrlsGeneratorInterface
{
public function __construct(
#[Autowire('%kernel.enabled_locales%')]
private array $locales,
){}

public function getAlias(): string
{
return 'static_pages';
}

/**
* @return iterable<Url|string>
*/
public function generateUrls(): iterable
{
foreach ($this->locales as $locale) {
yield Url::create(
'app_homepage',
[
'_locale' => $locale,
]
);
}
}
}
2 changes: 1 addition & 1 deletion templates/base.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
{% block javascripts %}
{% block importmap %}{{ importmap('app') }}{% endblock %}
{% endblock %}
{{ pwa() }}
{{ pwa(locale=app.request.locale) }}
</head>
<body>
{% block content %}
Expand Down
Loading

0 comments on commit cdaf355

Please sign in to comment.