Adding strings for all other languages
Some checks failed
Java CI with Gradle / build (17) (push) Failing after 1s
Java CI with Maven / build (17) (push) Failing after 1s

- Added WebConfiguration class to change language using url param
- Added text from messages to html files wherever required
- Added String to all other languages

Closes #1854

Signed-off-by: anizmo <potdar.anuj@gmail.com>
This commit is contained in:
anizmo 2025-04-15 22:51:56 -04:00 committed by Dave Syer
parent 332abbcb8a
commit 0c88f916db
16 changed files with 302 additions and 48 deletions

View file

@ -57,7 +57,7 @@ public class Owner extends Person {
@Column(name = "telephone")
@NotBlank
@Pattern(regexp = "\\d{10}", message = "Telephone must be a 10-digit number")
@Pattern(regexp = "\\d{10}", message = "{telephone.invalid}")
private String telephone;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)

View file

@ -0,0 +1,60 @@
package org.springframework.samples.petclinic.system;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import java.util.Locale;
/**
* Configures internationalization (i18n) support for the application.
*
* <p>
* Handles loading language-specific messages, tracking the user's language, and allowing
* language changes via the URL parameter (e.g., <code>?lang=de</code>).
* </p>
*
* @author Anuj Ashok Potdar
*/
@Configuration
@SuppressWarnings("unused")
public class WebConfiguration implements WebMvcConfigurer {
/**
* Uses session storage to remember the users language setting across requests.
* Defaults to English if nothing is specified.
* @return session-based {@link LocaleResolver}
*/
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver resolver = new SessionLocaleResolver();
resolver.setDefaultLocale(Locale.ENGLISH);
return resolver;
}
/**
* Allows the app to switch languages using a URL parameter like
* <code>?lang=es</code>.
* @return a {@link LocaleChangeInterceptor} that handles the change
*/
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
interceptor.setParamName("lang");
return interceptor;
}
/**
* Registers the locale change interceptor so it can run on each request.
* @param registry where interceptors are added
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
}

View file

@ -6,3 +6,28 @@ nonNumeric=must be all numeric
duplicateFormSubmission=Duplicate form submission is not allowed
typeMismatch.date=invalid date
typeMismatch.birthDate=invalid date
owner=Owner
firstName=First Name
lastName=Last Name
address=Address
city=City
telephone=Telephone
owners=Owners
addOwner=Add Owner
findOwner=Find Owner
findOwners=Find Owners
updateOwner=Update Owner
vets=Veterinarians
name=Name
specialties=Specialties
none=none
pages=pages
first=First
next=Next
previous=Previous
last=Last
somethingHappened=Something happened...
pets=Pets
home=Home
error=Error
telephone.invalid=Telephone must be a 10-digit number

View file

@ -6,4 +6,28 @@ nonNumeric=darf nur numerisch sein
duplicateFormSubmission=Wiederholtes Absenden des Formulars ist nicht erlaubt
typeMismatch.date=ung<EFBFBD>ltiges Datum
typeMismatch.birthDate=ung<EFBFBD>ltiges Datum
owner=Besitzer
firstName=Vorname
lastName=Nachname
address=Adresse
city=Stadt
telephone=Telefon
owners=Besitzer
addOwner=Besitzer hinzufügen
findOwner=Besitzer finden
findOwners=Besitzer suchen
updateOwner=Besitzer aktualisieren
vets=Tierärzte
name=Name
specialties=Fachgebiete
none=keine
pages=Seiten
first=Erste
next=Nächste
previous=Vorherige
last=Letzte
somethingHappened=Etwas ist passiert...
pets=Haustiere
home=Startseite
error=Fehler
telephone.invalid=Telefonnummer muss aus 10 Ziffern bestehen

View file

@ -6,4 +6,28 @@ nonNumeric=Sólo debe contener numeros
duplicateFormSubmission=No se permite el envío de formularios duplicados
typeMismatch.date=Fecha invalida
typeMismatch.birthDate=Fecha invalida
owner=Propietario
firstName=Nombre
lastName=Apellido
address=Dirección
city=Ciudad
telephone=Teléfono
owners=Propietarios
addOwner=Añadir propietario
findOwner=Buscar propietario
findOwners=Buscar propietarios
updateOwner=Actualizar propietario
vets=Veterinarios
name=Nombre
specialties=Especialidades
none=ninguno
pages=páginas
first=Primero
next=Siguiente
previous=Anterior
last=Último
somethingHappened=Algo pasó...
pets=Mascotas
home=Inicio
error=Error
telephone.invalid=El número de teléfono debe tener 10 dígitos

View file

@ -6,4 +6,28 @@ nonNumeric=باید عددی باشد
duplicateFormSubmission=ارسال تکراری فرم مجاز نیست
typeMismatch.date=تاریخ نامعتبر
typeMismatch.birthDate=تاریخ تولد نامعتبر
owner=مالک
firstName=نام
lastName=نام خانوادگی
address=آدرس
city=شهر
telephone=تلفن
owners=مالکان
addOwner=افزودن مالک
findOwner=یافتن مالک
findOwners=یافتن مالکان
updateOwner=ویرایش مالک
vets=دامپزشکان
name=نام
specialties=تخصص‌ها
none=هیچ‌کدام
pages=صفحات
first=اول
next=بعدی
previous=قبلی
last=آخر
somethingHappened=مشکلی پیش آمد...
pets=حیوانات خانگی
home=خانه
error=خطا
telephone.invalid=شماره تلفن باید ۱۰ رقمی باشد

View file

@ -6,3 +6,28 @@ nonNumeric=모두 숫자로 입력해야 합니다
duplicateFormSubmission=중복 제출은 허용되지 않습니다
typeMismatch.date=잘못된 날짜입니다
typeMismatch.birthDate=잘못된 날짜입니다
owner=소유자
firstName=이름
lastName=
address=주소
city=도시
telephone=전화번호
owners=소유자 목록
addOwner=소유자 추가
findOwner=소유자 찾기
findOwners=소유자들 찾기
updateOwner=소유자 수정
vets=수의사
name=이름
specialties=전문 분야
none=없음
pages=페이지
first=첫 번째
next=다음
previous=이전
last=마지막
somethingHappened=문제가 발생했습니다...
pets=반려동물
home=
error=오류
telephone.invalid=전화번호는 10자리 숫자여야 합니다

View file

@ -6,3 +6,28 @@ nonNumeric=Deve ser tudo numerico
duplicateFormSubmission=O envio duplicado de formulario nao e permitido
typeMismatch.date=Data invalida
typeMismatch.birthDate=Data de nascimento invalida
owner=Proprietário
firstName=Primeiro Nome
lastName=Sobrenome
address=Endereço
city=Cidade
telephone=Telefone
owners=Proprietários
addOwner=Adicionar proprietário
findOwner=Encontrar proprietário
findOwners=Encontrar proprietários
updateOwner=Atualizar proprietário
vets=Veterinários
name=Nome
specialties=Especialidades
none=nenhum
pages=páginas
first=Primeiro
next=Próximo
previous=Anterior
last=Último
somethingHappened=Algo aconteceu...
pets=Animais de estimação
home=Início
error=Erro
telephone.invalid=O número de telefone deve conter 10 dígitos

View file

@ -6,4 +6,28 @@ nonNumeric=должно быть все числовое значение
duplicateFormSubmission=Дублирование формы не допускается
typeMismatch.date=неправильная даные
typeMismatch.birthDate=неправильная дата
owner=Владелец
firstName=Имя
lastName=Фамилия
address=Адрес
city=Город
telephone=Телефон
owners=Владельцы
addOwner=Добавить владельца
findOwner=Найти владельца
findOwners=Найти владельцев
updateOwner=Обновить владельца
vets=Ветеринары
name=Имя
specialties=Специальности
none=нет
pages=страницы
first=Первый
next=Следующий
previous=Предыдущий
last=Последний
somethingHappened=Что-то пошло не так...
pets=Питомцы
home=Главная
error=Ошибка
telephone.invalid=Телефон должен содержать 10 цифр

View file

@ -6,4 +6,28 @@ nonNumeric=sadece sayısal olmalıdır
duplicateFormSubmission=Formun tekrar gönderilmesine izin verilmez
typeMismatch.date=geçersiz tarih
typeMismatch.birthDate=geçersiz tarih
owner=Sahip
firstName=Ad
lastName=Soyad
address=Adres
city=Şehir
telephone=Telefon
owners=Sahipler
addOwner=Sahip Ekle
findOwner=Sahip Bul
findOwners=Sahipleri Bul
updateOwner=Sahip Güncelle
vets=Veterinerler
name=İsim
specialties=Uzmanlıklar
none=yok
pages=sayfalar
first=İlk
next=Sonraki
previous=Önceki
last=Son
somethingHappened=Bir şey oldu...
pets=Evcil Hayvanlar
home=Ana Sayfa
error=Hata
telephone.invalid=Telefon numarası 10 basamaklı olmalıdır

View file

@ -4,7 +4,7 @@
<body>
<img src="../static/resources/images/pets.png" th:src="@{/resources/images/pets.png}"/>
<h2>Something happened...</h2>
<h2 th:text="#{somethingHappened}">Something happened...</h2>
<p th:text="${message}">Exception message</p>
</body>

View file

@ -45,25 +45,25 @@
<ul class="nav navbar-nav me-auto">
<li th:replace="~{::menuItem ('/','home','home page','home','Home')}">
<li th:replace="~{::menuItem ('/','home','home page','home',#{home})}">
<span class="fa fa-home" aria-hidden="true"></span>
<span>Home</span>
<span th:text="#{home}">Home</span>
</li>
<li th:replace="~{::menuItem ('/owners/find','owners','find owners','search','Find owners')}">
<li th:replace="~{::menuItem ('/owners/find','owners','find owners','search',#{findOwners})}">
<span class="fa fa-search" aria-hidden="true"></span>
<span>Find owners</span>
<span th:text="#{findOwners}">Find owners</span>
</li>
<li th:replace="~{::menuItem ('/vets.html','vets','veterinarians','th-list','Veterinarians')}">
<li th:replace="~{::menuItem ('/vets.html','vets','veterinarians','th-list',#{vets})}">
<span class="fa fa-th-list" aria-hidden="true"></span>
<span>Veterinarians</span>
<span th:text="#{vets}">Veterinarians</span>
</li>
<li
th:replace="~{::menuItem ('/oups','error','trigger a RuntimeException to see how it is handled','exclamation-triangle','Error')}">
th:replace="~{::menuItem ('/oups','error','trigger a RuntimeException to see how it is handled','exclamation-triangle',#{error})}">
<span class="fa exclamation-triangle" aria-hidden="true"></span>
<span>Error</span>
<span th:text="#{error}">Error</span>
</li>
</ul>

View file

@ -3,24 +3,24 @@
<body>
<h2>Owner</h2>
<h2 th:text="#{owner}">Owner</h2>
<form th:object="${owner}" class="form-horizontal" id="add-owner-form" method="post">
<div class="form-group has-feedback">
<input
th:replace="~{fragments/inputField :: input ('First Name', 'firstName', 'text')}" />
th:replace="~{fragments/inputField :: input (#{firstName}, 'firstName', 'text')}" />
<input
th:replace="~{fragments/inputField :: input ('Last Name', 'lastName', 'text')}" />
th:replace="~{fragments/inputField :: input (#{lastName}, 'lastName', 'text')}" />
<input
th:replace="~{fragments/inputField :: input ('Address', 'address', 'text')}" />
th:replace="~{fragments/inputField :: input (#{address}, 'address', 'text')}" />
<input
th:replace="~{fragments/inputField :: input ('City', 'city', 'text')}" />
th:replace="~{fragments/inputField :: input (#{city}, 'city', 'text')}" />
<input
th:replace="~{fragments/inputField :: input ('Telephone', 'telephone', 'text')}" />
th:replace="~{fragments/inputField :: input (#{telephone}, 'telephone', 'text')}" />
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button
th:with="text=${owner['new']} ? 'Add Owner' : 'Update Owner'"
th:with="text=${owner['new']} ? #{addOwner} : #{updateOwner}"
class="btn btn-primary" type="submit" th:text="${text}">Add
Owner</button>
</div>

View file

@ -3,13 +3,13 @@
<body>
<h2>Find Owners</h2>
<h2 th:text="#{findOwners}">Find Owners</h2>
<form th:object="${owner}" th:action="@{/owners}" method="get"
class="form-horizontal" id="search-owner-form">
<div class="form-group">
<div class="control-group" id="lastNameGroup">
<label class="col-sm-2 control-label">Last name </label>
<label class="col-sm-2 control-label" th:text="#{lastName}">Last name </label>
<div class="col-sm-10">
<input class="form-control" th:field="*{lastName}" size="30"
maxlength="80" /> <span class="help-inline"><div
@ -21,12 +21,11 @@
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">Find
Owner</button>
<button type="submit" class="btn btn-primary" th:text="#{findOwner}">Find Owner</button>
</div>
</div>
<a class="btn btn-primary" th:href="@{/owners/new}">Add Owner</a>
<a class="btn btn-primary" th:href="@{/owners/new}" th:text="#{addOwner}">Add Owner</a>
</form>

View file

@ -4,16 +4,16 @@
<body>
<h2>Owners</h2>
<h2 th:text="#{owners}">Owners</h2>
<table id="owners" class="table table-striped">
<thead>
<tr>
<th style="width: 150px;">Name</th>
<th style="width: 200px;">Address</th>
<th>City</th>
<th style="width: 120px">Telephone</th>
<th>Pets</th>
<th th:text="#{name}" style="width: 150px;">Name</th>
<th th:text="#{address}" style="width: 200px;">Address</th>
<th th:text="#{city}">City</th>
<th th:text="#{telephone}" style="width: 120px">Telephone</th>
<th th:text="#{pets}">Pets</th>
</tr>
</thead>
<tbody>
@ -29,7 +29,7 @@
</tbody>
</table>
<div th:if="${totalPages > 1}">
<span>Pages:</span>
<span th:text="#{pages}">Pages:</span>
<span>[</span>
<span th:each="i: ${#numbers.sequence(1, totalPages)}">
<a th:if="${currentPage != i}" th:href="@{'/owners?page=' + ${i}}">[[${i}]]</a>

View file

@ -5,13 +5,13 @@
<body>
<h2>Veterinarians</h2>
<h2 th:text="#{vets}">Veterinarians</h2>
<table id="vets" class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Specialties</th>
<th th:text="#{name}">Name</th>
<th th:text="#{specialties}">Specialties</th>
</tr>
</thead>
<tbody>
@ -19,13 +19,13 @@
<td th:text="${vet.firstName + ' ' + vet.lastName}"></td>
<td><span th:each="specialty : ${vet.specialties}"
th:text="${specialty.name + ' '}"/> <span
th:if="${vet.nrOfSpecialties == 0}">none</span></td>
th:if="${vet.nrOfSpecialties == 0}" th:text="#{none}">none</span></td>
</tr>
</tbody>
</table>
<div th:if="${totalPages > 1}">
<span>Pages:</span>
<span th:text="#{pages}">Pages:</span>
<span>[</span>
<span th:each="i: ${#numbers.sequence(1, totalPages)}">
<a th:if="${currentPage != i}" th:href="@{'/vets.html?page=__${i}__'}">[[${i}]]</a>
@ -33,24 +33,24 @@
</span>
<span>]&nbsp;</span>
<span>
<a th:if="${currentPage > 1}" th:href="@{'/vets.html?page=1'}" title="First"
<a th:if="${currentPage > 1}" th:href="@{'/vets.html?page=1'}" title=#{first}
class="fa fa-fast-backward"></a>
<span th:unless="${currentPage > 1}" title="First" class="fa fa-fast-backward"></span>
<span th:unless="${currentPage > 1}" th:text="#{first}" title=#{first} class="fa fa-fast-backward"></span>
</span>
<span>
<a th:if="${currentPage > 1}" th:href="@{'/vets.html?page=__${currentPage - 1}__'}" title="Previous"
<a th:if="${currentPage > 1}" th:href="@{'/vets.html?page=__${currentPage - 1}__'}" title=#{previous}
class="fa fa-step-backward"></a>
<span th:unless="${currentPage > 1}" title="Previous" class="fa fa-step-backward"></span>
<span th:unless="${currentPage > 1}" th:text="#{previous}" title=#{previous} class="fa fa-step-backward"></span>
</span>
<span>
<a th:if="${currentPage < totalPages}" th:href="@{'/vets.html?page=__${currentPage + 1}__'}" title="Next"
<a th:if="${currentPage < totalPages}" th:href="@{'/vets.html?page=__${currentPage + 1}__'}" title=#{next}
class="fa fa-step-forward"></a>
<span th:unless="${currentPage < totalPages}" title="Next" class="fa fa-step-forward"></span>
<span th:unless="${currentPage < totalPages}" th:text="#{next}" title=#{next} class="fa fa-step-forward"></span>
</span>
<span>
<a th:if="${currentPage < totalPages}" th:href="@{'/vets.html?page=__${totalPages}__'}" title="Last"
<a th:if="${currentPage < totalPages}" th:href="@{'/vets.html?page=__${totalPages}__'}" title=#{last}
class="fa fa-fast-forward"></a>
<span th:unless="${currentPage < totalPages}" title="Last" class="fa fa-fast-forward"></span>
<span th:unless="${currentPage < totalPages}" th:text="#{last}" class="fa fa-fast-forward"></span>
</span>
</div>
</body>