๐ฅ Settings & TransTag
๐ฅ Translation File
๐ฅ get_current_language
๐ฅ Python code Translation
โ๏ธ Django Translation์ ๊ตญ๊ฐ ์ค์ ์ ํตํด ํ์ด์ง๋ฅผ ๋ฒ์ญํด์ฃผ๋ ๊ธฐ๋ฅ์ ๋๋ค. ์ด๋ฅผ ์ํด์ "locale" ๋๋ ํ ๋ฆฌ๋ฅผ ํ๋ก์ ํธ ๋๋ ํ ๋ฆฌ ์๋ ๋ง๋ค์ด์ค๋๋ค.
โ๏ธ "locale" ๋๋ ํ ๋ฆฌ์๋ Translation ํ์ผ์ด ์ ์ฅ๋ ์ฅ์๋ก ์ฌ์ฉ๋ฉ๋๋ค. 'locale" ๋๋ ํ ๋ฆฌ๋ฅผ ์์ฑ ํ settings.py์์ Translation ํ์ผ์ "locale"์ ์ ์ฅํ๋ผ๊ณ Django์๊ฒ ๊ฒฝ๋ก๋ฅผ ์๋ ค์ค๋๋ค.
# settings.py MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", "django.middleware.locale.LocaleMiddleware", # ๐ ์ถ๊ฐ ] ... ... ... # Locale LOCALE_PATHS = (os.path.join(BASE_DIR, "locale"),)
โ๏ธ ์ด์ HTML์ ์ด๋ ๋ถ๋ถ์ Django์๊ฒ ๋ฒ์ญ์ํฌ์ง ์์ญ์ ์ง์ ํด ์ค๋๋ค. "footer"์ "search bar"์ "placeholder" ๋ถ๋ถ์ Translation ์์ญ์ผ๋ก ์ง์ ํด๋ณด๊ฒ ์ต๋๋ค.
โ๏ธ ์ง์ ์ ์ํด์๋ HTML ํ์ผ ์ต์๋จ์ i18n์ loadํด์ผํ๋๋ฐ์, internationaliztion ์ ์ค์๋ง์ด i18n์
๋๋ค.
โ๏ธ "internationaliztion"์ load ์์ผฐ๋ค๋ฉด, ๋ฒ์ญ์ด ํ์ํ ์์ญ์ trans ํ ํ๋ฆฟ ์ฝ๋๋ฅผ ์ ์ฉ์ํต๋๋ค.
# footer.html {% load i18n %} # ๐ load "i18n" <footer class="container mx-auto text-center py-10 border-t font-medium text-gray-500"> <span> {% trans "Please don't copy us." %} </span> # ๐ trnas ํ ํ๋ฆฟ ์ฝ๋ <span> © 2021 Airbnb-Clone, {% trans "All rights reserved" %}. </span> </footer>
# base.html {% load static i18n %} # ๐ load "i18n" <!DOCTYPE html> <html lang="en"> ... ... <form method="get" action="{% url "rooms:search" %}" class="w-9/12"> <input class="search-box border px-5 w-full font-medium text-gray-900 placeholder-gray-600 py-3 rounded-sm shadow-md hover:shadow-lg focus:outline-none" name="city" placeholder="{% trans "Search By City" %}" # ๐ trnas ํ ํ๋ฆฟ ์ฝ๋ /> </form> </html>
โ๏ธ ๋จ์ด๋ฅผ ํ๋ํ๋ ๋ณ๊ฒฝํ ๋๋ trans ํ ํ๋ฆฟ ํ ๊ทธ๋ฅผ ์ฌ์ฉํ ์ ์์ง๋ง, ์์ญ์ ์ง์ ํด์ ๋ณ๊ฒฝํ ๋๋ blocktrans ํ๊ทธ๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๋งฅ๋ฝ์ด ์ค์ํ ๋๋ ์ด ๋ฐฉ๋ฒ์ด ๋ ์ ์ฉํ๊ฒ ์ฌ์ฉ๋ฉ๋๋ค. blockrans๋ฅผ ์ฌ์ฉํ ๋๋ ๋ง์ฐฌ๊ฐ์ง๋ก i18n์ loadํด์ผ ํฉ๋๋ค.
โ๏ธ blocktrans๋ ํ ํ๋ฆฟ ๋ณ์๋ฅผ ์๋์ผ๋ก ์ธ์ํ ์ ์์ต๋๋ค. ์ด์ ํ ํ๋ฆฟ ๋ณ์๋ฅผ ์ธ์์ํค๊ธฐ ์ํด ํ์ํ ๋ณ์๋ฅผ blocktrans ๋ด์์ with ๊ตฌ๋ฌธ ์ฌ์ฉํ์ฌ ์ง์ ํฉ๋๋ค.
{% extends "base.html" %} {% load i18n %} # ๐ "i18n" load {% block page_title %} Home {% endblock page_title %} {% block content %} ... ... <span class="mx-3 font-medium text-lg"> {% blocktrans with # ๐ ๋ณ์๋ฅผ ์ง์ ํ ๋ค, ์ฌ์ฉํด์ผ ์ธ์ํฉ๋๋ค. current_page=page_obj.number total_pages=page_obj.paginator.num_pages %}Page {{current_page}} of {{total_pages}} {% endblocktrans %} </span> ... ...
โ๏ธ Translation์ ๊ฒฝ๋ก๋ฅผ settings.py์์ ์ค์ ํ๊ณ , HTML์์ ๋ฒ์ญํ ์์ญ์ ์ง์ ํ์์ต๋๋ค. ์ด์ Django์๊ฒ ๋ฒ์ญํ ์ธ์ด์ ํจ๊ปmakemessage ๋ช ๋ น์ ๋ด๋ ค์ฃผ๋ฉด ๋ฉ๋๋ค.
โ๏ธ ๋ง์ผ ๋ช ๋ น์์ ์ค๋ฅ๊ฐ ๋๋ค๋ฉด, gettext๊ฐ ์ค์น๋์ง ์์์ ์ ์์ด์. ์๋์ ๋ช ๋ น์ ์คํํด๋ณด์ธ์:)
โ๏ธ gettext๊ฐ ์ค์น์ ์ฐ๊ฒฐ์ด ์ ๋์ด์๊ณ , makemessages ๋ช ๋ น์ ๋ฌธ์ ๊ฐ ์๋ค๋ฉด, locale ํด๋์ "django.po"๋ ํ์ผ์ด ์์ฑ๋์ด ์์ต๋๋ค. ์ฐ๋ฆฌ๊ฐ "locale" ๋๋ ํ ๋ฆฌ์ ํ์ผ ๊ฒฝ๋ก๋ฅผ ์ง์ ํ ์ด์ ๋ ๋ฐ๋ก ์ด๋ฅผ ์ํจ์ ๋๋ค.
#: templates/base.html:24 msgid "Search By City" msgstr "" #: templates/partials/footer.html:3 msgid "Please don't copy us." msgstr "" #: templates/partials/footer.html:4 msgid "All rights reserved" msgstr ""
โ๏ธ "makemessages" ๋ช ๋ น์ ํตํด Django๊ฐ taggingํ ์์ญ์ ๋ชจ๋ ์ฐพ์ Translationํ ์ ์๊ฒ ํ์ผ์ ๋ง๋ค์ด ์ฃผ์์ต๋๋ค. ์ด์ "msgstr" ๋ถ๋ถ์ ๋ฒ์ญํ ๋ด์ฉ์ ์ ์ด์ค๋๋ค.
... ... #: templates/base.html:24 msgid "Search By City" msgstr "๋์๋ณ ๊ฒ์" #: templates/partials/footer.html:3 msgid "Please don't copy us." msgstr "์ ๋ฐ ์ฐ๋ฆฌ๋ฅผ ๋์ฉํ์ง ๋ง์ธ์." #: templates/partials/footer.html:4 msgid "All rights reserved" msgstr "ํ๊ถ ์์ " #: templates/rooms/room_list.html:24 #, python-format msgid "Page %(current_page)s of %(total_pages)s" msgstr "์ด %(total_pages)s ์ค %(current_page)s ์ชฝ" # ๐ s๊น์ง ์ฌ์ฉํด์ผํด์.
โ๏ธ "django.po"์์ ๋ฒ์ญํ ๋ด์ฉ์ ์์ฑํ์๋ค๋ฉด, compliemessages ๋ช ๋ น์ ๋ด๋ ค์ค๋๋ค. ์ด ๋ช ๋ น์ ์์ฑํ๋ฉด locale ๋๋ ํ ๋ฆฌ์ "django.mo" ํ์ผ์ด ์์ฑ๋ฉ๋๋ค.
โ๏ธ ์ด์ ์ฌ์ฉ์๊ฐ HTML์์ ์ธ์ด ์ ํ์ ํ ์ ์๋๋ก ์ ํ ๋ชฉ๋ก์ ๋ง๋ค์ด ์ฃผ๊ณ , ์ด ์ ํ ์ฌํญ์ ๋ฐ๋ผ ํ์ด์ง์ ์ธ์ด๊ฐ ๋ณ๊ฒฝ๋ ์ ์๋๋ก ํด๋ณด๊ฒ ์ต๋๋ค.
โ๏ธ ์ธ์ด ์ ํ์ ์ํด select ํ๊ทธ๋ฅผ ์ด์ฉํ์ฌ ์ ํ๋ชฉ๋ก์ ์ถ๊ฐํ๊ณ , ko๋ก ์ธ์ด๋ฅผ ๋ฐ๊ฟง๋ค๊ฐ, ๋ค์ en๋ก ๋์์ค๊ธฐ ์ํด์ "get_current_language"๋ฅผ ์ฌ์ฉํฉ๋๋ค.
# footer.html {% load i18n %} <footer class="container mx-auto text-center py-10 border-t font-medium text-gray-500"> <div class="flex flex-col"> <span> {% trans "Please don't copy us." %} </span<> <span>© 2021 AirBnb-Clone, {% trans "All rights reserved" %}.</span> </div> <div class="mt-10 flex"> {% get_current_language as LANGUAGE_CODE %} <select class="w-1/5 h-8" id="js-lang"> # ๐ js์์ ํด๋น ํ๊ทธ์ ๋ณํ๋ฅผ ๊ฐ์งํ ์ ์๊ฒ id๊ฐ์ ๋ฃ์ด ์ค๋๋ค. <option value="en" {% if LANGUAGE_CODE == 'en' %} selected {% endif %}>English </option> <option value="ko" {% if LANGUAGE_CODE == 'ko' %} selected {% endif %}>Korean </option> </select> </div> </footer>
โ๏ธ select ํ๊ทธ์ ๋ณํ๊ฐ ๋ฐ์ํ๋ฉด, addEventListener๋ฅผ ํตํด ์ด๋ฅผ ๊ฐ์งํ๊ณ ํ์ด์ง๋ฅผ ์๊ณ ๋ก์นจ(reload)ํ ์ ์๋๋ก javascript๋ฅผ ํ์ฉํ์ต๋๋ค.
โ๏ธ ๋ํ fetch๋ฅผ ํตํด ๊ฒฝ๋ก๋ฅผ ์ค์ ํด ์ฃผ์์ต๋๋ค.
{% url 'users:switch-language' %}?lang=${selected}
)<script> const langSelect = document.getElementById("js-lang"); const handleLangChange = () => { const selected = langSelect.value; // ๐ value๊ฐ ์ถ์ถ fetch(`{% url 'users:switch-language' %}?lang=${selected}`).then(() => window.location.reload()); } // ๐ ๊ฒฝ๋ก๋ก request๋ฅผ ๋ณด๋ด๊ณ , ๊ทธ๋ฌ๊ณ ๋์ ์๋ก๊ณ ์นจ langSelect.addEventListener("change", handleLangChange); // ๐ "js-lang"์ ๋ณํ๋ฅผ ๊ฐ์งํ๋ฉด, "handleLangChange" ํจ์ ์คํ </script>
โ๏ธ view์ url์ ๋งคํํด ์๋๋๋์ง ํ์ธํฉ๋๋ค.
โ๏ธ tranlation์ import ํ, url์์ ๊ฐ์ ธ์จ ์ธ์ด์ ๊ฐ์ด("langSelect.value") ์กด์ฌํ๋ค๋ฉด,, session์ ์ธ์ด ๊ฐ์ ์ถ๊ฐํด์ค๋๋ค.
#user/views.py from django.http import HttpResponse # ๐ "HttpResponse" ์ถ๊ฐ from django.utils import translation # ๐ "translation" ์ถ๊ฐ ... ... def switch_language(request): lang = request.GET.get("lang", None) if lang is not None: request.session[translation.LANGUAGE_SESSION_KEY] = lang # ๐ session์ ์ธ์ด๊ฐ ์ถ๊ฐ return HttpResponse(status=200)
#user/urls.py from django.urls import path from . import views app_name = "users" urlpatterns = [ ... ... path("switch-language/", views.switch_language, name="switch-language"), ]
โ๏ธ Template์์ Translationํ๋ ๋ฐฉ๋ฒ์ ์์ ๋ณด์์ผ๋, python code๋ฅผ Translationํ๋ ๋ฐฉ๋ฒ์ ์์๋ณผ๊ป์:)
โ๏ธ ์ด๋ฅผ ์ํด gettext_lazy๋ฅผ importํฉ๋๋ค. ์ด๋ reverselazy์ฒ๋ผ ์ฆ๊ฐ์ ์ผ๋ก ์คํ๋๋ ๊ฒ์ด ์๋๋ผ, ์ฝ๋๊ฐ ํธ์ถ๋์์ ๋๋ง ๋ฐ์ํด์.
โ๏ธ gettextlazy๋ฅผ `๋ก ์ฌ์ฉํ๊ธฐ๋ก ํ์์ผ๋,
_`์ ์ธ์๋ก ์ ๋ฌํ์ฌ makemessages๋ฅผ ๋ช
๋ น์ํต๋๋ค.
# users/models.py from django.utils.translation import gettext_lazy as _ # ๐ gettext_lazy ํธ์ถ ... # Create your models here. class User(AbstractUser): GENDER_MALE = "male" GENDER_FEMALE = "female" GENDER_OTHER = "other" GENDER_CHOICES = ( (GENDER_MALE, _("Male")), # ๐ _()๋ก gettext_lazy๋ฅผ ํธ์ถํฉ๋๋ค. (GENDER_FEMALE, _("Female")), # ๐ _()๋ก gettext_lazy๋ฅผ ํธ์ถํฉ๋๋ค. (GENDER_OTHER, _("Other")), # ๐ _()๋ก gettext_lazy๋ฅผ ํธ์ถํฉ๋๋ค. ) LANGUAGE_ENGLISH = "en" LANGUAGE_KOREAN = "kr" LANGUAGE_CHOICES = ( (LANGUAGE_ENGLISH, _("English")), # ๐ _()๋ก gettext_lazy๋ฅผ ํธ์ถํฉ๋๋ค. (LANGUAGE_KOREAN, _("Korean")), # ๐ _()๋ก gettext_lazy๋ฅผ ํธ์ถํฉ๋๋ค. ) ... ... avatar = models.ImageField(upload_to="avatars", blank=True) gender = models.CharField( _("gender"), choices=GENDER_CHOICES, max_length=10, blank=True ) # ๐ _()๋ก gettext_lazy๋ฅผ ํธ์ถํฉ๋๋ค. bio = models.TextField(blank=True) birthdate = models.DateField(null=True, blank=True) language = models.CharField( _("language"), # ๐ _()๋ก gettext_lazy๋ฅผ ํธ์ถํฉ๋๋ค. choices=LANGUAGE_CHOICES, max_length=2, blank=True, default=LANGUAGE_KOREAN, ) ... ...
โ๏ธ msgstr์ ๋ค ์์ฑํ ํ์ compile๋ ์งํํด์ฃผ์ด์ผ ํฉ๋๋ค.
#: users/models.py:20 msgid "Male" msgstr "๋จ์ฑ" #: users/models.py:21 msgid "Female" msgstr "์ฌ์ฑ" #: users/models.py:22 msgid "Other" msgstr "๊ธฐํ" #: users/models.py:29 msgid "English" msgstr "์์ด" #: users/models.py:30 msgid "Korean" msgstr "ํ๊ตญ์ด" #: users/models.py:53 msgid "gender" msgstr "์ฑ๋ณ" #: users/models.py:58 msgid "language" msgstr "์ธ์ด" #: users/models.py:85 msgid "Verify Airbnb Account" msgstr "Airbnb ๊ณ์ ์ธ์ฆ"