Features: 1) None;
Fixes: 1) None; Extra: 1) Removed the entire "geo" module, including migrations, model definitions, admin configurations, utilities, documentation, templates, translations, and related files. Moved functionality to "core".
|
|
@ -27,10 +27,3 @@ db_backups/
|
||||||
services_data/
|
services_data/
|
||||||
static/
|
static/
|
||||||
media/
|
media/
|
||||||
node_modules//geo/data/admin1CodesASCII.txt
|
|
||||||
/geo/data/admin2Codes.txt
|
|
||||||
/geo/data/allCountries.zip
|
|
||||||
/geo/data/alternateNames.zip
|
|
||||||
/geo/data/cities5000.zip
|
|
||||||
/geo/data/countryInfo.txt
|
|
||||||
/geo/data/hierarchy.zip
|
|
||||||
1
.gitignore
vendored
|
|
@ -81,7 +81,6 @@ services_data/postgres/*
|
||||||
services_data/redis/*
|
services_data/redis/*
|
||||||
static
|
static
|
||||||
!core/static
|
!core/static
|
||||||
!geo/static
|
|
||||||
!payments/static
|
!payments/static
|
||||||
!vibes_auth/static
|
!vibes_auth/static
|
||||||
media
|
media
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ from constance.admin import ConstanceAdmin as BaseConstanceAdmin
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.admin import ModelAdmin, TabularInline
|
from django.contrib.admin import ModelAdmin, TabularInline
|
||||||
|
from django.contrib.gis.admin import GISModelAdmin
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from mptt.admin import DraggableMPTTAdmin
|
from mptt.admin import DraggableMPTTAdmin
|
||||||
|
|
@ -11,6 +12,7 @@ from evibes.settings import CONSTANCE_CONFIG, LANGUAGES
|
||||||
|
|
||||||
from .forms import OrderForm, OrderProductForm, VendorForm
|
from .forms import OrderForm, OrderProductForm, VendorForm
|
||||||
from .models import (
|
from .models import (
|
||||||
|
Address,
|
||||||
Attribute,
|
Attribute,
|
||||||
AttributeGroup,
|
AttributeGroup,
|
||||||
AttributeValue,
|
AttributeValue,
|
||||||
|
|
@ -360,6 +362,21 @@ class ProductImageAdmin(BasicModelAdmin):
|
||||||
autocomplete_fields = ("product",)
|
autocomplete_fields = ("product",)
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Address)
|
||||||
|
class AddressAdmin(GISModelAdmin):
|
||||||
|
list_display = ("street", "city", "region", "country", "user")
|
||||||
|
list_filter = ("country", "region")
|
||||||
|
search_fields = ("raw_data", "street", "city", "postal_code", "user__email")
|
||||||
|
|
||||||
|
gis_widget_kwargs = {
|
||||||
|
"attrs": {
|
||||||
|
"default_lon": 37.61556,
|
||||||
|
"default_lat": 55.75222,
|
||||||
|
"default_zoom": 6,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ConstanceAdmin(BaseConstanceAdmin):
|
class ConstanceAdmin(BaseConstanceAdmin):
|
||||||
def get_urls(self):
|
def get_urls(self):
|
||||||
info = f"{self.model._meta.app_label}_{self.model._meta.model_name}"
|
info = f"{self.model._meta.app_label}_{self.model._meta.model_name}"
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,9 @@ from rest_framework import status
|
||||||
from core.docs.drf import BASE_ERRORS
|
from core.docs.drf import BASE_ERRORS
|
||||||
from core.serializers import (
|
from core.serializers import (
|
||||||
AddOrderProductSerializer,
|
AddOrderProductSerializer,
|
||||||
|
AddressAutocompleteInputSerializer,
|
||||||
|
AddressSerializer,
|
||||||
|
AddressSuggestionSerializer,
|
||||||
AddWishlistProductSerializer,
|
AddWishlistProductSerializer,
|
||||||
AttributeDetailSerializer,
|
AttributeDetailSerializer,
|
||||||
AttributeGroupDetailSerializer,
|
AttributeGroupDetailSerializer,
|
||||||
|
|
@ -438,3 +441,59 @@ PRODUCT_SCHEMA = {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ADDRESS_SCHEMA = {
|
||||||
|
"list": extend_schema(
|
||||||
|
summary=_("list all addresses"),
|
||||||
|
responses={
|
||||||
|
status.HTTP_200_OK: AddressSerializer(many=True),
|
||||||
|
**BASE_ERRORS,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
"retrieve": extend_schema(
|
||||||
|
summary=_("retrieve a single address"),
|
||||||
|
responses={
|
||||||
|
status.HTTP_200_OK: AddressSerializer,
|
||||||
|
**BASE_ERRORS,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
"create": extend_schema(
|
||||||
|
summary=_("create a new address"),
|
||||||
|
request=AddressSerializer,
|
||||||
|
responses={
|
||||||
|
status.HTTP_201_CREATED: AddressSerializer,
|
||||||
|
**BASE_ERRORS,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
"destroy": extend_schema(
|
||||||
|
summary=_("delete an address"),
|
||||||
|
responses={
|
||||||
|
status.HTTP_204_NO_CONTENT: {},
|
||||||
|
**BASE_ERRORS,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
"update": extend_schema(
|
||||||
|
summary=_("update an entire address"),
|
||||||
|
request=AddressSerializer,
|
||||||
|
responses={
|
||||||
|
status.HTTP_200_OK: AddressSerializer,
|
||||||
|
**BASE_ERRORS,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
"partial_update": extend_schema(
|
||||||
|
summary=_("partially update an address"),
|
||||||
|
request=AddressSerializer,
|
||||||
|
responses={
|
||||||
|
status.HTTP_200_OK: AddressSerializer,
|
||||||
|
**BASE_ERRORS,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
"autocomplete": extend_schema(
|
||||||
|
summary=_("autocomplete address suggestions"),
|
||||||
|
request=AddressAutocompleteInputSerializer,
|
||||||
|
responses={
|
||||||
|
status.HTTP_200_OK: AddressSuggestionSerializer(many=True),
|
||||||
|
**BASE_ERRORS,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,13 @@ from graphene_django.utils import camelize
|
||||||
|
|
||||||
from core.elasticsearch import process_query
|
from core.elasticsearch import process_query
|
||||||
from core.graphene import BaseMutation
|
from core.graphene import BaseMutation
|
||||||
from core.graphene.object_types import OrderType, ProductType, SearchResultsType, WishlistType
|
from core.graphene.object_types import AddressType, OrderType, ProductType, SearchResultsType, WishlistType
|
||||||
from core.models import Category, Order, Product, Wishlist
|
from core.models import Address, Category, Order, Product, Wishlist
|
||||||
from core.utils import format_attributes, is_url_safe
|
from core.utils import format_attributes, is_url_safe
|
||||||
from core.utils.caching import web_cache
|
from core.utils.caching import web_cache
|
||||||
from core.utils.emailing import contact_us_email
|
from core.utils.emailing import contact_us_email
|
||||||
from core.utils.messages import permission_denied_message
|
from core.utils.messages import permission_denied_message
|
||||||
|
from core.utils.nominatim import fetch_address_suggestions
|
||||||
from payments.graphene.object_types import TransactionType
|
from payments.graphene.object_types import TransactionType
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
@ -455,6 +456,70 @@ class DeleteProduct(BaseMutation):
|
||||||
return DeleteProduct(ok=True)
|
return DeleteProduct(ok=True)
|
||||||
|
|
||||||
|
|
||||||
|
class CreateAddress(BaseMutation):
|
||||||
|
class Arguments:
|
||||||
|
raw_data = String(
|
||||||
|
required=True,
|
||||||
|
description=_("original address string provided by the user")
|
||||||
|
)
|
||||||
|
|
||||||
|
address = Field(AddressType)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def mutate(_parent, info, raw_data):
|
||||||
|
user = info.context.user if info.context.user.is_authenticated else None
|
||||||
|
|
||||||
|
address = Address.objects.create(
|
||||||
|
raw_data=raw_data,
|
||||||
|
user=user
|
||||||
|
)
|
||||||
|
return CreateAddress(address=address)
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteAddress(BaseMutation):
|
||||||
|
class Arguments:
|
||||||
|
uuid = UUID(required=True)
|
||||||
|
|
||||||
|
success = Boolean()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def mutate(_parent, info, uuid):
|
||||||
|
try:
|
||||||
|
address = Address.objects.get(uuid=uuid)
|
||||||
|
if (
|
||||||
|
info.context.user.is_superuser
|
||||||
|
or info.context.user.has_perm("core.delete_address")
|
||||||
|
or info.context.user == address.user
|
||||||
|
):
|
||||||
|
address.delete()
|
||||||
|
return DeleteAddress(success=True)
|
||||||
|
|
||||||
|
raise PermissionDenied(permission_denied_message)
|
||||||
|
|
||||||
|
except Address.DoesNotExist:
|
||||||
|
name = "Address"
|
||||||
|
raise Http404(_(f"{name} does not exist: {uuid}"))
|
||||||
|
|
||||||
|
|
||||||
|
class AutocompleteAddress(BaseMutation):
|
||||||
|
class Arguments:
|
||||||
|
q = String()
|
||||||
|
limit = Int()
|
||||||
|
|
||||||
|
suggestions = GenericScalar()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def mutate(_parent, info, q, limit):
|
||||||
|
if 1 > limit > 10:
|
||||||
|
raise BadRequest(_("limit must be between 1 and 10"))
|
||||||
|
try:
|
||||||
|
suggestions = fetch_address_suggestions(query=q, limit=limit)
|
||||||
|
except Exception as e:
|
||||||
|
raise BadRequest(f"geocoding error: {e!s}") from e
|
||||||
|
|
||||||
|
return AutocompleteAddress(suggestions=suggestions)
|
||||||
|
|
||||||
|
|
||||||
class ContactUs(BaseMutation):
|
class ContactUs(BaseMutation):
|
||||||
class Arguments:
|
class Arguments:
|
||||||
email = String(required=True)
|
email = String(required=True)
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,8 @@ from core.models import (
|
||||||
Promotion,
|
Promotion,
|
||||||
Stock,
|
Stock,
|
||||||
Vendor,
|
Vendor,
|
||||||
Wishlist,
|
Wishlist, Address,
|
||||||
)
|
)
|
||||||
from geo.graphene.object_types import AddressType
|
|
||||||
|
|
||||||
logger = __import__("logging").getLogger(__name__)
|
logger = __import__("logging").getLogger(__name__)
|
||||||
|
|
||||||
|
|
@ -359,6 +358,33 @@ class ProductType(DjangoObjectType):
|
||||||
return self.quantity or 0
|
return self.quantity or 0
|
||||||
|
|
||||||
|
|
||||||
|
class AddressType(DjangoObjectType):
|
||||||
|
latitude = Float(description=_("Latitude (Y coordinate)"))
|
||||||
|
longitude = Float(description=_("Longitude (X coordinate)"))
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Address
|
||||||
|
fields = (
|
||||||
|
"uuid",
|
||||||
|
"street",
|
||||||
|
"district",
|
||||||
|
"city",
|
||||||
|
"region",
|
||||||
|
"postal_code",
|
||||||
|
"country",
|
||||||
|
"raw_data",
|
||||||
|
"api_response",
|
||||||
|
"user",
|
||||||
|
)
|
||||||
|
read_only_fields = ("api_response",)
|
||||||
|
|
||||||
|
def resolve_latitude(self, info):
|
||||||
|
return self.location.y if self.location else None
|
||||||
|
|
||||||
|
def resolve_longitude(self, info):
|
||||||
|
return self.location.x if self.location else None
|
||||||
|
|
||||||
|
|
||||||
class AttributeValueType(DjangoObjectType):
|
class AttributeValueType(DjangoObjectType):
|
||||||
value = String(description=_("attribute value"))
|
value = String(description=_("attribute value"))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,15 @@ from core.filters import (
|
||||||
from core.graphene.mutations import (
|
from core.graphene.mutations import (
|
||||||
AddOrderProduct,
|
AddOrderProduct,
|
||||||
AddWishlistProduct,
|
AddWishlistProduct,
|
||||||
|
AutocompleteAddress,
|
||||||
BuyOrder,
|
BuyOrder,
|
||||||
BuyProduct,
|
BuyProduct,
|
||||||
BuyWishlist,
|
BuyWishlist,
|
||||||
CacheOperator,
|
CacheOperator,
|
||||||
ContactUs,
|
ContactUs,
|
||||||
|
CreateAddress,
|
||||||
CreateProduct,
|
CreateProduct,
|
||||||
|
DeleteAddress,
|
||||||
DeleteProduct,
|
DeleteProduct,
|
||||||
RemoveAllOrderProducts,
|
RemoveAllOrderProducts,
|
||||||
RemoveAllWishlistProducts,
|
RemoveAllWishlistProducts,
|
||||||
|
|
@ -70,7 +73,6 @@ from core.utils import get_project_parameters
|
||||||
from core.utils.languages import get_flag_by_language
|
from core.utils.languages import get_flag_by_language
|
||||||
from core.utils.messages import permission_denied_message
|
from core.utils.messages import permission_denied_message
|
||||||
from evibes.settings import LANGUAGES
|
from evibes.settings import LANGUAGES
|
||||||
from geo.graphene.mutations import AutocompleteAddress, CreateAddress, DeleteAddress
|
|
||||||
from payments.graphene.mutations import Deposit
|
from payments.graphene.mutations import Deposit
|
||||||
from vibes_auth.filters import UserFilter
|
from vibes_auth.filters import UserFilter
|
||||||
from vibes_auth.graphene.mutations import (
|
from vibes_auth.graphene.mutations import (
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ class Command(BaseCommand):
|
||||||
action="append",
|
action="append",
|
||||||
required=True,
|
required=True,
|
||||||
metavar="APP",
|
metavar="APP",
|
||||||
help="App label for translation, e.g. core, geo."
|
help="App label for translation, e.g. core, payments."
|
||||||
)
|
)
|
||||||
|
|
||||||
def handle(self, *args, **options) -> None:
|
def handle(self, *args, **options) -> None:
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ class Command(BaseCommand):
|
||||||
action='append',
|
action='append',
|
||||||
required=True,
|
required=True,
|
||||||
metavar='APP',
|
metavar='APP',
|
||||||
help='App label(s) to scan, e.g. core, geo'
|
help='App label(s) to scan, e.g. core, payments'
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-p', '--path',
|
'-p', '--path',
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
import requests
|
||||||
|
from constance import config
|
||||||
|
from django.contrib.gis.geos import Point
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class AddressManager(models.Manager):
|
||||||
|
def create(self, raw_data: str, **kwargs):
|
||||||
|
"""
|
||||||
|
Create an Address instance by geocoding the provided raw address string.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
raw_data (str): The raw address input from the user (e.g., '36 Mornington Rd Loughton England').
|
||||||
|
**kwargs: Additional fields to pass to the Address model (e.g., user).
|
||||||
|
"""
|
||||||
|
if not raw_data:
|
||||||
|
raise ValueError("'raw_data' (address string) must be provided.")
|
||||||
|
|
||||||
|
# Query Nominatim
|
||||||
|
params = {
|
||||||
|
'format': 'json',
|
||||||
|
'addressdetails': 1,
|
||||||
|
'q': raw_data,
|
||||||
|
}
|
||||||
|
resp = requests.get(config.NOMINATIM_URL, params=params)
|
||||||
|
resp.raise_for_status()
|
||||||
|
results = resp.json()
|
||||||
|
if not results:
|
||||||
|
raise ValueError(f"No geocoding result for address: {raw_data}")
|
||||||
|
data = results[0]
|
||||||
|
|
||||||
|
# Parse address components
|
||||||
|
addr = data.get('address', {})
|
||||||
|
street = addr.get('road') or addr.get('pedestrian') or ''
|
||||||
|
district = addr.get('city_district') or addr.get('suburb') or ''
|
||||||
|
city = addr.get('city') or addr.get('town') or addr.get('village') or ''
|
||||||
|
region = addr.get('state') or addr.get('region') or ''
|
||||||
|
postal_code = addr.get('postcode') or ''
|
||||||
|
country = addr.get('country') or ''
|
||||||
|
|
||||||
|
# Parse location
|
||||||
|
try:
|
||||||
|
lat = float(data.get('lat'))
|
||||||
|
lon = float(data.get('lon'))
|
||||||
|
location = Point(lon, lat, srid=4326)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
location = None
|
||||||
|
|
||||||
|
# Create the model instance, storing both the input string and full API response
|
||||||
|
return super().create(
|
||||||
|
raw_data=raw_data,
|
||||||
|
street=street,
|
||||||
|
district=district,
|
||||||
|
city=city,
|
||||||
|
region=region,
|
||||||
|
postal_code=postal_code,
|
||||||
|
country=country,
|
||||||
|
location=location,
|
||||||
|
api_response=data,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
@ -15,10 +15,6 @@ import core.validators
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('geo', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Feedback',
|
name='Feedback',
|
||||||
|
|
@ -991,14 +987,6 @@ class Migration(migrations.Migration):
|
||||||
('buy_time',
|
('buy_time',
|
||||||
models.DateTimeField(blank=True, default=None, help_text='the timestamp when the order was finalized',
|
models.DateTimeField(blank=True, default=None, help_text='the timestamp when the order was finalized',
|
||||||
null=True, verbose_name='buy time')),
|
null=True, verbose_name='buy time')),
|
||||||
('billing_address',
|
|
||||||
models.ForeignKey(blank=True, help_text='the billing address used for this order', null=True,
|
|
||||||
on_delete=django.db.models.deletion.CASCADE, related_name='billing_address_order',
|
|
||||||
to='geo.address', verbose_name='billing address')),
|
|
||||||
('shipping_address',
|
|
||||||
models.ForeignKey(blank=True, help_text='the shipping address used for this order', null=True,
|
|
||||||
on_delete=django.db.models.deletion.CASCADE, related_name='shipping_address_order',
|
|
||||||
to='geo.address', verbose_name='shipping address')),
|
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'verbose_name': 'order',
|
'verbose_name': 'order',
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 5.2 on 2025-05-19 11:38
|
# Generated by Django 5.2 on 2025-05-20 04:57
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
|
@ -10,9 +10,8 @@ from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
initial = True
|
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
('core', '0018_alter_order_human_readable_id'),
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -38,20 +37,20 @@ class Migration(migrations.Migration):
|
||||||
('region', models.CharField(max_length=100, null=True, verbose_name='region')),
|
('region', models.CharField(max_length=100, null=True, verbose_name='region')),
|
||||||
('postal_code', models.CharField(max_length=20, null=True, verbose_name='postal code')),
|
('postal_code', models.CharField(max_length=20, null=True, verbose_name='postal code')),
|
||||||
('country', models.CharField(max_length=40, null=True, verbose_name='country')),
|
('country', models.CharField(max_length=40, null=True, verbose_name='country')),
|
||||||
('location', django.contrib.gis.db.models.PointField(blank=True, geography=True,
|
('location', django.contrib.gis.db.models.fields.PointField(blank=True, geography=True,
|
||||||
help_text='Geolocation point: (longitude, latitude)',
|
help_text='geolocation point: (longitude, latitude)',
|
||||||
null=True, srid=4326)),
|
null=True, srid=4326)),
|
||||||
('raw_data', models.JSONField(blank=True, help_text='Full JSON response from geocoder for this address',
|
('raw_data', models.JSONField(blank=True, help_text='full JSON response from geocoder for this address',
|
||||||
null=True)),
|
null=True)),
|
||||||
('api_response',
|
('api_response',
|
||||||
models.JSONField(blank=True, help_text='Stored JSON response from the geocoding service', null=True)),
|
models.JSONField(blank=True, help_text='stored JSON response from the geocoding service', null=True)),
|
||||||
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE,
|
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE,
|
||||||
to=settings.AUTH_USER_MODEL)),
|
to=settings.AUTH_USER_MODEL)),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'verbose_name': 'address',
|
'verbose_name': 'address',
|
||||||
'verbose_name_plural': 'addresses',
|
'verbose_name_plural': 'addresses',
|
||||||
'indexes': [models.Index(fields=['location'], name='geo_address_locatio_83b064_idx')],
|
'indexes': [models.Index(fields=['location'], name='core_addres_locatio_eb6b39_idx')],
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Generated by Django 5.2 on 2025-05-20 04:59
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
('core', '0019_address'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='order',
|
||||||
|
name='billing_address',
|
||||||
|
field=models.ForeignKey(blank=True, help_text='the billing address used for this order', null=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE, related_name='billing_address_order',
|
||||||
|
to='core.address', verbose_name='billing address'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='order',
|
||||||
|
name='shipping_address',
|
||||||
|
field=models.ForeignKey(blank=True, help_text='the shipping address used for this order', null=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE, related_name='shipping_address_order',
|
||||||
|
to='core.address', verbose_name='shipping address'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -4,6 +4,7 @@ import logging
|
||||||
from typing import Self
|
from typing import Self
|
||||||
|
|
||||||
from constance import config
|
from constance import config
|
||||||
|
from django.contrib.gis.db.models import PointField
|
||||||
from django.contrib.postgres.indexes import GinIndex
|
from django.contrib.postgres.indexes import GinIndex
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.core.exceptions import BadRequest, ValidationError
|
from django.core.exceptions import BadRequest, ValidationError
|
||||||
|
|
@ -28,6 +29,7 @@ from django.db.models import (
|
||||||
PositiveIntegerField,
|
PositiveIntegerField,
|
||||||
TextField,
|
TextField,
|
||||||
)
|
)
|
||||||
|
from django.db.models.indexes import Index
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.encoding import force_bytes
|
from django.utils.encoding import force_bytes
|
||||||
|
|
@ -40,11 +42,11 @@ from mptt.models import MPTTModel
|
||||||
from core.abstract import NiceModel
|
from core.abstract import NiceModel
|
||||||
from core.choices import ORDER_PRODUCT_STATUS_CHOICES, ORDER_STATUS_CHOICES
|
from core.choices import ORDER_PRODUCT_STATUS_CHOICES, ORDER_STATUS_CHOICES
|
||||||
from core.errors import DisabledCommerceError, NotEnoughMoneyError
|
from core.errors import DisabledCommerceError, NotEnoughMoneyError
|
||||||
|
from core.managers import AddressManager
|
||||||
from core.utils import generate_human_readable_id, get_product_uuid_as_path, get_random_code
|
from core.utils import generate_human_readable_id, get_product_uuid_as_path, get_random_code
|
||||||
from core.utils.lists import FAILED_STATUSES
|
from core.utils.lists import FAILED_STATUSES
|
||||||
from core.validators import validate_category_image_dimensions
|
from core.validators import validate_category_image_dimensions
|
||||||
from evibes.settings import CURRENCY_CODE
|
from evibes.settings import CURRENCY_CODE
|
||||||
from geo.models import Address
|
|
||||||
from payments.models import Transaction
|
from payments.models import Transaction
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
@ -433,7 +435,7 @@ class Order(NiceModel):
|
||||||
is_publicly_visible = False
|
is_publicly_visible = False
|
||||||
|
|
||||||
billing_address = ForeignKey(
|
billing_address = ForeignKey(
|
||||||
"geo.Address",
|
"core.Address",
|
||||||
on_delete=CASCADE,
|
on_delete=CASCADE,
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
|
|
@ -450,7 +452,7 @@ class Order(NiceModel):
|
||||||
verbose_name=_("applied promo code"),
|
verbose_name=_("applied promo code"),
|
||||||
)
|
)
|
||||||
shipping_address = ForeignKey(
|
shipping_address = ForeignKey(
|
||||||
"geo.Address",
|
"core.Address",
|
||||||
on_delete=CASCADE,
|
on_delete=CASCADE,
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
|
|
@ -1225,3 +1227,52 @@ class Documentary(NiceModel):
|
||||||
@property
|
@property
|
||||||
def file_type(self):
|
def file_type(self):
|
||||||
return self.document.name.split(".")[-1] or _("unresolved")
|
return self.document.name.split(".")[-1] or _("unresolved")
|
||||||
|
|
||||||
|
|
||||||
|
class Address(NiceModel):
|
||||||
|
street = CharField(_("street"), max_length=255, null=True) # noqa: DJ001
|
||||||
|
district = CharField(_("district"), max_length=255, null=True) # noqa: DJ001
|
||||||
|
city = CharField(_("city"), max_length=100, null=True) # noqa: DJ001
|
||||||
|
region = CharField(_("region"), max_length=100, null=True) # noqa: DJ001
|
||||||
|
postal_code = CharField(_("postal code"), max_length=20, null=True) # noqa: DJ001
|
||||||
|
country = CharField(_("country"), max_length=40, null=True) # noqa: DJ001
|
||||||
|
|
||||||
|
location = PointField(
|
||||||
|
geography=True,
|
||||||
|
srid=4326,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
help_text=_("geolocation point: (longitude, latitude)")
|
||||||
|
)
|
||||||
|
|
||||||
|
raw_data = JSONField(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
help_text=_("full JSON response from geocoder for this address")
|
||||||
|
)
|
||||||
|
|
||||||
|
api_response = JSONField(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
help_text=_("stored JSON response from the geocoding service")
|
||||||
|
)
|
||||||
|
|
||||||
|
user = ForeignKey(
|
||||||
|
to="vibes_auth.User",
|
||||||
|
on_delete=CASCADE,
|
||||||
|
blank=True,
|
||||||
|
null=True
|
||||||
|
)
|
||||||
|
|
||||||
|
objects = AddressManager()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("address")
|
||||||
|
verbose_name_plural = _("addresses")
|
||||||
|
indexes = [
|
||||||
|
Index(fields=["location"]),
|
||||||
|
]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
base = f"{self.street}, {self.city}, {self.country}"
|
||||||
|
return f"{base} for {self.user.email}" if self.user else base
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,18 @@
|
||||||
from rest_framework.fields import BooleanField, CharField, Field, IntegerField, JSONField, ListField, UUIDField
|
from rest_framework.fields import (
|
||||||
|
BooleanField,
|
||||||
|
CharField,
|
||||||
|
DictField,
|
||||||
|
Field,
|
||||||
|
FloatField,
|
||||||
|
IntegerField,
|
||||||
|
JSONField,
|
||||||
|
ListField,
|
||||||
|
UUIDField,
|
||||||
|
)
|
||||||
from rest_framework.serializers import ListSerializer, Serializer
|
from rest_framework.serializers import ListSerializer, Serializer
|
||||||
|
|
||||||
|
from core.models import Address
|
||||||
|
|
||||||
from .detail import * # noqa: F403
|
from .detail import * # noqa: F403
|
||||||
from .simple import * # noqa: F403
|
from .simple import * # noqa: F403
|
||||||
|
|
||||||
|
|
@ -91,3 +103,65 @@ class BuyAsBusinessOrderSerializer(Serializer):
|
||||||
billing_business_address_uuid = CharField(required=False)
|
billing_business_address_uuid = CharField(required=False)
|
||||||
shipping_business_address_uuid = CharField(required=False)
|
shipping_business_address_uuid = CharField(required=False)
|
||||||
payment_method = CharField(required=True)
|
payment_method = CharField(required=True)
|
||||||
|
|
||||||
|
|
||||||
|
class AddressAutocompleteInputSerializer(Serializer):
|
||||||
|
q = CharField(
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
limit = IntegerField(
|
||||||
|
required=False,
|
||||||
|
min_value=1,
|
||||||
|
max_value=10,
|
||||||
|
default=5
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AddressSuggestionSerializer(Serializer):
|
||||||
|
display_name = CharField()
|
||||||
|
lat = FloatField()
|
||||||
|
lon = FloatField()
|
||||||
|
address = DictField(child=CharField())
|
||||||
|
|
||||||
|
|
||||||
|
class AddressSerializer(ModelSerializer): # noqa: F405
|
||||||
|
latitude = FloatField(source="location.y", read_only=True)
|
||||||
|
longitude = FloatField(source="location.x", read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Address
|
||||||
|
fields = [
|
||||||
|
"uuid",
|
||||||
|
"street",
|
||||||
|
"district",
|
||||||
|
"city",
|
||||||
|
"region",
|
||||||
|
"postal_code",
|
||||||
|
"country",
|
||||||
|
"latitude",
|
||||||
|
"longitude",
|
||||||
|
"raw_data",
|
||||||
|
"api_response",
|
||||||
|
"user",
|
||||||
|
]
|
||||||
|
read_only_fields = [
|
||||||
|
"latitude",
|
||||||
|
"longitude",
|
||||||
|
"raw_data",
|
||||||
|
"api_response",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class AddressCreateSerializer(ModelSerializer): # noqa: F405
|
||||||
|
raw_data = CharField(
|
||||||
|
write_only=True,
|
||||||
|
max_length=512,
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Address
|
||||||
|
fields = ["raw_data", "user"]
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
raw = validated_data.pop("raw_data")
|
||||||
|
return Address.objects.create(raw_data=raw, **validated_data)
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 122 B After Width: | Height: | Size: 122 B |
|
Before Width: | Height: | Size: 269 B After Width: | Height: | Size: 269 B |
|
Before Width: | Height: | Size: 126 B After Width: | Height: | Size: 126 B |
|
Before Width: | Height: | Size: 99 B After Width: | Height: | Size: 99 B |
|
Before Width: | Height: | Size: 288 B After Width: | Height: | Size: 288 B |
|
Before Width: | Height: | Size: 261 B After Width: | Height: | Size: 261 B |
|
Before Width: | Height: | Size: 348 B After Width: | Height: | Size: 348 B |
|
Before Width: | Height: | Size: 108 B After Width: | Height: | Size: 108 B |
|
Before Width: | Height: | Size: 192 B After Width: | Height: | Size: 192 B |
|
Before Width: | Height: | Size: 112 B After Width: | Height: | Size: 112 B |
|
Before Width: | Height: | Size: 239 B After Width: | Height: | Size: 239 B |
|
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 282 B |
|
Before Width: | Height: | Size: 99 B After Width: | Height: | Size: 99 B |
|
Before Width: | Height: | Size: 98 B After Width: | Height: | Size: 98 B |
|
Before Width: | Height: | Size: 513 B After Width: | Height: | Size: 513 B |
|
Before Width: | Height: | Size: 108 B After Width: | Height: | Size: 108 B |
|
Before Width: | Height: | Size: 99 B After Width: | Height: | Size: 99 B |
|
Before Width: | Height: | Size: 225 B After Width: | Height: | Size: 225 B |
|
|
@ -16,6 +16,7 @@ from rest_framework_xml.renderers import XMLRenderer
|
||||||
from rest_framework_yaml.renderers import YAMLRenderer
|
from rest_framework_yaml.renderers import YAMLRenderer
|
||||||
|
|
||||||
from core.docs.drf.viewsets import (
|
from core.docs.drf.viewsets import (
|
||||||
|
ADDRESS_SCHEMA,
|
||||||
ATTRIBUTE_GROUP_SCHEMA,
|
ATTRIBUTE_GROUP_SCHEMA,
|
||||||
ATTRIBUTE_SCHEMA,
|
ATTRIBUTE_SCHEMA,
|
||||||
ATTRIBUTE_VALUE_SCHEMA,
|
ATTRIBUTE_VALUE_SCHEMA,
|
||||||
|
|
@ -26,6 +27,7 @@ from core.docs.drf.viewsets import (
|
||||||
)
|
)
|
||||||
from core.filters import BrandFilter, CategoryFilter, OrderFilter, ProductFilter
|
from core.filters import BrandFilter, CategoryFilter, OrderFilter, ProductFilter
|
||||||
from core.models import (
|
from core.models import (
|
||||||
|
Address,
|
||||||
Attribute,
|
Attribute,
|
||||||
AttributeGroup,
|
AttributeGroup,
|
||||||
AttributeValue,
|
AttributeValue,
|
||||||
|
|
@ -46,6 +48,9 @@ from core.models import (
|
||||||
from core.permissions import EvibesPermission
|
from core.permissions import EvibesPermission
|
||||||
from core.serializers import (
|
from core.serializers import (
|
||||||
AddOrderProductSerializer,
|
AddOrderProductSerializer,
|
||||||
|
AddressAutocompleteInputSerializer,
|
||||||
|
AddressCreateSerializer,
|
||||||
|
AddressSerializer,
|
||||||
AddWishlistProductSerializer,
|
AddWishlistProductSerializer,
|
||||||
AttributeDetailSerializer,
|
AttributeDetailSerializer,
|
||||||
AttributeGroupDetailSerializer,
|
AttributeGroupDetailSerializer,
|
||||||
|
|
@ -80,6 +85,7 @@ from core.serializers import (
|
||||||
)
|
)
|
||||||
from core.utils import format_attributes
|
from core.utils import format_attributes
|
||||||
from core.utils.messages import permission_denied_message
|
from core.utils.messages import permission_denied_message
|
||||||
|
from core.utils.nominatim import fetch_address_suggestions
|
||||||
from payments.serializers import TransactionProcessSerializer
|
from payments.serializers import TransactionProcessSerializer
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -461,3 +467,34 @@ class WishlistViewSet(EvibesViewSet):
|
||||||
return Response(status=status.HTTP_200_OK, data=WishlistDetailSerializer(wishlist).data)
|
return Response(status=status.HTTP_200_OK, data=WishlistDetailSerializer(wishlist).data)
|
||||||
except Order.DoesNotExist:
|
except Order.DoesNotExist:
|
||||||
return Response(status=status.HTTP_404_NOT_FOUND)
|
return Response(status=status.HTTP_404_NOT_FOUND)
|
||||||
|
|
||||||
|
|
||||||
|
@extend_schema_view(**ADDRESS_SCHEMA)
|
||||||
|
class AddressViewSet(EvibesViewSet):
|
||||||
|
queryset = Address.objects.all()
|
||||||
|
serializer_class = AddressSerializer
|
||||||
|
|
||||||
|
def get_serializer_class(self):
|
||||||
|
if self.action == 'create':
|
||||||
|
return AddressCreateSerializer
|
||||||
|
if self.action == 'autocomplete':
|
||||||
|
return AddressAutocompleteInputSerializer
|
||||||
|
return AddressSerializer
|
||||||
|
|
||||||
|
@action(detail=False, methods=["get"], url_path="autocomplete")
|
||||||
|
def autocomplete(self, request):
|
||||||
|
serializer = AddressAutocompleteInputSerializer(data=request.query_params)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
|
||||||
|
q = serializer.validated_data["q"]
|
||||||
|
limit = serializer.validated_data["limit"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
suggestions = fetch_address_suggestions(query=q, limit=limit)
|
||||||
|
except Exception as e:
|
||||||
|
return Response(
|
||||||
|
{"detail": _(f"Geocoding error: {e}")},
|
||||||
|
status=status.HTTP_502_BAD_GATEWAY,
|
||||||
|
)
|
||||||
|
|
||||||
|
return Response(suggestions, status=status.HTTP_200_OK)
|
||||||
|
|
|
||||||
|
|
@ -14,17 +14,18 @@ urlpatterns = [
|
||||||
path(r"graphql/", csrf_exempt(CustomGraphQLView.as_view(graphiql=True, schema=schema))),
|
path(r"graphql/", csrf_exempt(CustomGraphQLView.as_view(graphiql=True, schema=schema))),
|
||||||
path(
|
path(
|
||||||
r"docs/",
|
r"docs/",
|
||||||
SpectacularAPIView.as_view(urlconf="evibes.api_urls", custom_settings=SPECTACULAR_PLATFORM_SETTINGS),
|
SpectacularAPIView.as_view(urlconf="evibes.api_urls",
|
||||||
|
custom_settings=SPECTACULAR_PLATFORM_SETTINGS),
|
||||||
name="schema-platform",
|
name="schema-platform",
|
||||||
),
|
),
|
||||||
path(r"docs/swagger/", CustomSwaggerView.as_view(url_name="schema-platform"), name="swagger-ui-platform"),
|
path(r"docs/swagger/", CustomSwaggerView.as_view(url_name="schema-platform"),
|
||||||
|
name="swagger-ui-platform"),
|
||||||
path(r"docs/redoc/", CustomRedocView.as_view(url_name="schema-platform"), name="redoc-ui-platform"),
|
path(r"docs/redoc/", CustomRedocView.as_view(url_name="schema-platform"), name="redoc-ui-platform"),
|
||||||
path(r"i18n/", include("django.conf.urls.i18n")),
|
path(r"i18n/", include("django.conf.urls.i18n")),
|
||||||
path(r"favicon.ico", favicon_view),
|
path(r"favicon.ico", favicon_view),
|
||||||
path(r"", index),
|
path(r"", index),
|
||||||
path(r"", include("core.api_urls")),
|
path(r"", include("core.api_urls")),
|
||||||
path(r"auth/", include("vibes_auth.urls")),
|
path(r"auth/", include("vibes_auth.urls")),
|
||||||
path(r"geo/", include("geo.urls")),
|
|
||||||
path(r"payments/", include("payments.urls")),
|
path(r"payments/", include("payments.urls")),
|
||||||
path(r"blog/", include("blog.urls")),
|
path(r"blog/", include("blog.urls")),
|
||||||
] + i18n_patterns(path("admin/", admin.site.urls))
|
] + i18n_patterns(path("admin/", admin.site.urls))
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,6 @@ INSTALLED_APPS = [
|
||||||
"django_mailbox",
|
"django_mailbox",
|
||||||
"graphene_django",
|
"graphene_django",
|
||||||
"core",
|
"core",
|
||||||
"geo",
|
|
||||||
"payments",
|
"payments",
|
||||||
"vibes_auth",
|
"vibes_auth",
|
||||||
"blog",
|
"blog",
|
||||||
|
|
@ -120,7 +119,6 @@ TEMPLATES = [
|
||||||
"DIRS": [
|
"DIRS": [
|
||||||
BASE_DIR / "vibes_auth/templates",
|
BASE_DIR / "vibes_auth/templates",
|
||||||
BASE_DIR / "core/templates",
|
BASE_DIR / "core/templates",
|
||||||
BASE_DIR / "geo/templates",
|
|
||||||
BASE_DIR / "payments/templates",
|
BASE_DIR / "payments/templates",
|
||||||
],
|
],
|
||||||
"APP_DIRS": True,
|
"APP_DIRS": True,
|
||||||
|
|
@ -249,39 +247,32 @@ DAISY_SETTINGS = {
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"apps": "",
|
"apps": "",
|
||||||
},
|
},
|
||||||
"geo": {
|
|
||||||
"icon": "fa fa-solid fa-globe",
|
|
||||||
"hide": False,
|
|
||||||
"app": "geo",
|
|
||||||
"priority": 2,
|
|
||||||
"apps": "",
|
|
||||||
},
|
|
||||||
"payments": {
|
"payments": {
|
||||||
"icon": "fa fa-solid fa-wallet",
|
"icon": "fa fa-solid fa-wallet",
|
||||||
"hide": False,
|
"hide": False,
|
||||||
"app": "payments",
|
"app": "payments",
|
||||||
"priority": 3,
|
"priority": 2,
|
||||||
"apps": "",
|
"apps": "",
|
||||||
},
|
},
|
||||||
"blog": {
|
"blog": {
|
||||||
"icon": "fa fa-solid fa-book",
|
"icon": "fa fa-solid fa-book",
|
||||||
"hide": False,
|
"hide": False,
|
||||||
"app": "blog",
|
"app": "blog",
|
||||||
"priority": 4,
|
"priority": 3,
|
||||||
"apps": "",
|
"apps": "",
|
||||||
},
|
},
|
||||||
"core": {
|
"core": {
|
||||||
"icon": "fa fa-solid fa-house",
|
"icon": "fa fa-solid fa-house",
|
||||||
"hide": False,
|
"hide": False,
|
||||||
"app": "core",
|
"app": "core",
|
||||||
"priority": 5,
|
"priority": 4,
|
||||||
"apps": "",
|
"apps": "",
|
||||||
},
|
},
|
||||||
"vibes_auth": {
|
"vibes_auth": {
|
||||||
"icon": "fa fa-solid fa-user",
|
"icon": "fa fa-solid fa-user",
|
||||||
"hide": False,
|
"hide": False,
|
||||||
"app": "vibes_auth",
|
"app": "vibes_auth",
|
||||||
"priority": 6,
|
"priority": 5,
|
||||||
"apps": "",
|
"apps": "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -32,5 +32,4 @@ else:
|
||||||
"vibes_auth.*": {"ops": {"fetch", "get"}, "timeout": 60 * 60},
|
"vibes_auth.*": {"ops": {"fetch", "get"}, "timeout": 60 * 60},
|
||||||
"auth.permission": {"ops": "all", "timeout": 60 * 60},
|
"auth.permission": {"ops": "all", "timeout": 60 * 60},
|
||||||
"core.*": {"ops": "all", "timeout": 60 * 60},
|
"core.*": {"ops": "all", "timeout": 60 * 60},
|
||||||
"geo.*": {"ops": "all", "timeout": 60 * 60},
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
19
geo/admin.py
|
|
@ -1,19 +0,0 @@
|
||||||
from django.contrib import admin
|
|
||||||
from django.contrib.gis.admin import GISModelAdmin
|
|
||||||
|
|
||||||
from .models import Address
|
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Address)
|
|
||||||
class AddressAdmin(GISModelAdmin):
|
|
||||||
list_display = ("street", "city", "region", "country", "user")
|
|
||||||
list_filter = ("country", "region")
|
|
||||||
search_fields = ("raw_data", "street", "city", "postal_code", "user__email")
|
|
||||||
|
|
||||||
gis_widget_kwargs = {
|
|
||||||
"attrs": {
|
|
||||||
"default_lon": 37.61556,
|
|
||||||
"default_lat": 55.75222,
|
|
||||||
"default_zoom": 6,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
from django.apps import AppConfig
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
|
|
||||||
|
|
||||||
class GeoConfig(AppConfig):
|
|
||||||
default_auto_field = "django.db.models.BigAutoField"
|
|
||||||
name = "geo"
|
|
||||||
verbose_name = _("geodata")
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
from drf_spectacular.utils import inline_serializer
|
|
||||||
from rest_framework import status
|
|
||||||
from rest_framework.fields import CharField
|
|
||||||
|
|
||||||
error = inline_serializer("error", fields={"detail": CharField()})
|
|
||||||
|
|
||||||
BASE_ERRORS = {
|
|
||||||
status.HTTP_400_BAD_REQUEST: error,
|
|
||||||
status.HTTP_401_UNAUTHORIZED: error,
|
|
||||||
status.HTTP_403_FORBIDDEN: error,
|
|
||||||
status.HTTP_404_NOT_FOUND: error,
|
|
||||||
status.HTTP_405_METHOD_NOT_ALLOWED: error,
|
|
||||||
status.HTTP_500_INTERNAL_SERVER_ERROR: error,
|
|
||||||
}
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
from drf_spectacular.utils import extend_schema
|
|
||||||
from rest_framework import status
|
|
||||||
|
|
||||||
from core.docs.drf import BASE_ERRORS
|
|
||||||
from geo.serializers import AddressAutocompleteInputSerializer, AddressSerializer, AddressSuggestionSerializer
|
|
||||||
|
|
||||||
ADDRESS_SCHEMA = {
|
|
||||||
"list": extend_schema(
|
|
||||||
summary=_("list all addresses"),
|
|
||||||
responses={
|
|
||||||
status.HTTP_200_OK: AddressSerializer(many=True),
|
|
||||||
**BASE_ERRORS,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
"retrieve": extend_schema(
|
|
||||||
summary=_("retrieve a single address"),
|
|
||||||
responses={
|
|
||||||
status.HTTP_200_OK: AddressSerializer,
|
|
||||||
**BASE_ERRORS,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
"create": extend_schema(
|
|
||||||
summary=_("create a new address"),
|
|
||||||
request=AddressSerializer,
|
|
||||||
responses={
|
|
||||||
status.HTTP_201_CREATED: AddressSerializer,
|
|
||||||
**BASE_ERRORS,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
"destroy": extend_schema(
|
|
||||||
summary=_("delete an address"),
|
|
||||||
responses={
|
|
||||||
status.HTTP_204_NO_CONTENT: {},
|
|
||||||
**BASE_ERRORS,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
"update": extend_schema(
|
|
||||||
summary=_("update an entire address"),
|
|
||||||
request=AddressSerializer,
|
|
||||||
responses={
|
|
||||||
status.HTTP_200_OK: AddressSerializer,
|
|
||||||
**BASE_ERRORS,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
"partial_update": extend_schema(
|
|
||||||
summary=_("partially update an address"),
|
|
||||||
request=AddressSerializer,
|
|
||||||
responses={
|
|
||||||
status.HTTP_200_OK: AddressSerializer,
|
|
||||||
**BASE_ERRORS,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
"autocomplete": extend_schema(
|
|
||||||
summary=_("autocomplete address suggestions"),
|
|
||||||
request=AddressAutocompleteInputSerializer,
|
|
||||||
responses={
|
|
||||||
status.HTTP_200_OK: AddressSuggestionSerializer(many=True),
|
|
||||||
**BASE_ERRORS,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
import graphene
|
|
||||||
from django.core.exceptions import BadRequest
|
|
||||||
from django.http import Http404
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
from graphene.types.generic import GenericScalar
|
|
||||||
from rest_framework.exceptions import PermissionDenied
|
|
||||||
|
|
||||||
from core.graphene import BaseMutation
|
|
||||||
from core.utils.messages import permission_denied_message
|
|
||||||
from geo.graphene.object_types import AddressType
|
|
||||||
from geo.models import Address
|
|
||||||
from geo.utils.nominatim import fetch_address_suggestions
|
|
||||||
|
|
||||||
|
|
||||||
class CreateAddress(graphene.Mutation):
|
|
||||||
class Arguments:
|
|
||||||
raw_data = graphene.String(
|
|
||||||
required=True,
|
|
||||||
description=_("original address string provided by the user")
|
|
||||||
)
|
|
||||||
|
|
||||||
address = graphene.Field(AddressType)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def mutate(_parent, info, raw_data):
|
|
||||||
user = info.context.user if info.context.user.is_authenticated else None
|
|
||||||
|
|
||||||
address = Address.objects.create(
|
|
||||||
raw_data=raw_data,
|
|
||||||
user=user
|
|
||||||
)
|
|
||||||
return CreateAddress(address=address)
|
|
||||||
|
|
||||||
|
|
||||||
class DeleteAddress(BaseMutation):
|
|
||||||
class Arguments:
|
|
||||||
uuid = graphene.UUID(required=True)
|
|
||||||
|
|
||||||
success = graphene.Boolean()
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def mutate(_parent, info, uuid):
|
|
||||||
try:
|
|
||||||
address = Address.objects.get(uuid=uuid)
|
|
||||||
if (
|
|
||||||
info.context.user.is_superuser
|
|
||||||
or info.context.user.has_perm("geo.delete_address")
|
|
||||||
or info.context.user == address.user
|
|
||||||
):
|
|
||||||
address.delete()
|
|
||||||
return DeleteAddress(success=True)
|
|
||||||
|
|
||||||
raise PermissionDenied(permission_denied_message)
|
|
||||||
|
|
||||||
except Address.DoesNotExist:
|
|
||||||
name = "Address"
|
|
||||||
raise Http404(_(f"{name} does not exist: {uuid}"))
|
|
||||||
|
|
||||||
|
|
||||||
class AutocompleteAddress(BaseMutation):
|
|
||||||
class Arguments:
|
|
||||||
q = graphene.String()
|
|
||||||
limit = graphene.Int()
|
|
||||||
|
|
||||||
suggestions = GenericScalar()
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def mutate(_parent, info, q, limit):
|
|
||||||
if 1 > limit > 10:
|
|
||||||
raise BadRequest(_("limit must be between 1 and 10"))
|
|
||||||
try:
|
|
||||||
suggestions = fetch_address_suggestions(query=q, limit=limit)
|
|
||||||
except Exception as e:
|
|
||||||
raise BadRequest(f"geocoding error: {e!s}") from e
|
|
||||||
|
|
||||||
return AutocompleteAddress(suggestions=suggestions)
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
import graphene
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
from graphene import Float, ObjectType, String
|
|
||||||
from graphene.types.generic import GenericScalar
|
|
||||||
from graphene_django import DjangoObjectType
|
|
||||||
|
|
||||||
from geo.models import Address
|
|
||||||
|
|
||||||
|
|
||||||
class AddressAutocompleteInput(graphene.InputObjectType):
|
|
||||||
q = graphene.String(
|
|
||||||
required=True,
|
|
||||||
description=_("partial or full address string to search for")
|
|
||||||
)
|
|
||||||
limit = graphene.Int(
|
|
||||||
required=False,
|
|
||||||
description=_("maximum number of suggestions to return (1–10)"),
|
|
||||||
default_value=5
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class AddressSuggestionType(ObjectType):
|
|
||||||
display_name = String()
|
|
||||||
lat = Float()
|
|
||||||
lon = Float()
|
|
||||||
address = GenericScalar(
|
|
||||||
description=_("the address breakdown as key/value pairs")
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class AddressType(DjangoObjectType):
|
|
||||||
latitude = graphene.Float(description=_("Latitude (Y coordinate)"))
|
|
||||||
longitude = graphene.Float(description=_("Longitude (X coordinate)"))
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Address
|
|
||||||
fields = (
|
|
||||||
"uuid",
|
|
||||||
"street",
|
|
||||||
"district",
|
|
||||||
"city",
|
|
||||||
"region",
|
|
||||||
"postal_code",
|
|
||||||
"country",
|
|
||||||
"raw_data",
|
|
||||||
"api_response",
|
|
||||||
"user",
|
|
||||||
)
|
|
||||||
read_only_fields = ("api_response",)
|
|
||||||
|
|
||||||
def resolve_latitude(self, info):
|
|
||||||
return self.location.y if self.location else None
|
|
||||||
|
|
||||||
def resolve_longitude(self, info):
|
|
||||||
return self.location.x if self.location else None
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
# eVibes Translations.
|
|
||||||
# Copyright (C) 2025 Egor "fureunoir" Gorbunov
|
|
||||||
# This file is distributed under the same license as the eVibes package.
|
|
||||||
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: 1\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2025-04-28 16:26+0100\n"
|
|
||||||
"PO-Revision-Date: 2025-01-30 03:27+0000\n"
|
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language-Team: ARABIC <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language: ARABIC\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: geo/apps.py:8
|
|
||||||
msgid "geodata"
|
|
||||||
msgstr "البيانات الجغرافية"
|
|
||||||
|
|
||||||
#: geo/conf.py:407
|
|
||||||
msgid "Name"
|
|
||||||
msgstr "الاسم"
|
|
||||||
|
|
||||||
#: geo/conf.py:408
|
|
||||||
msgid "Abbreviation"
|
|
||||||
msgstr "الاختصار"
|
|
||||||
|
|
||||||
#: geo/conf.py:409
|
|
||||||
msgid "Link"
|
|
||||||
msgstr "رابط إلى"
|
|
||||||
|
|
||||||
#: geo/conf.py:413
|
|
||||||
msgid "IATA (Airport) Code"
|
|
||||||
msgstr "رمز (مطار) IATA (المطار)"
|
|
||||||
|
|
||||||
#: geo/conf.py:414
|
|
||||||
msgid "ICAO (Airport) Code"
|
|
||||||
msgstr "رمز (مطار) منظمة الطيران المدني الدولي (ICAO)"
|
|
||||||
|
|
||||||
#: geo/conf.py:415
|
|
||||||
msgid "FAAC (Airport) Code"
|
|
||||||
msgstr "الرمز (المطار) FAAC (المطار)"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:30
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {city_uuid}"
|
|
||||||
msgstr "{name} غير موجود: {city_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:33
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {postal_code_uuid}"
|
|
||||||
msgstr "{name} غير موجود: {postal_code_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {uuid}"
|
|
||||||
msgstr "{name} غير موجود: {uuid}"
|
|
||||||
|
|
||||||
#: geo/models.py:47
|
|
||||||
msgid "UUID"
|
|
||||||
msgstr "المعرف الفريد"
|
|
||||||
|
|
||||||
#: geo/models.py:48
|
|
||||||
msgid "active"
|
|
||||||
msgstr "نشط"
|
|
||||||
|
|
||||||
#: geo/models.py:54
|
|
||||||
msgid "subclasses_of_place_must_implement_slugify"
|
|
||||||
msgstr "يجب أن تنفذ الفئات الفرعية ل 'المكان' طريقة سلوغفايفي"
|
|
||||||
|
|
||||||
#: geo/models.py:123
|
|
||||||
msgid "continent"
|
|
||||||
msgstr "القارة"
|
|
||||||
|
|
||||||
#: geo/models.py:124
|
|
||||||
msgid "continents"
|
|
||||||
msgstr "القارات"
|
|
||||||
|
|
||||||
#: geo/models.py:149 geo/models.py:169
|
|
||||||
msgid "country"
|
|
||||||
msgstr "البلد"
|
|
||||||
|
|
||||||
#: geo/models.py:150 geo/models.py:170
|
|
||||||
msgid "countries"
|
|
||||||
msgstr "الدول"
|
|
||||||
|
|
||||||
#: geo/models.py:182
|
|
||||||
msgid "region"
|
|
||||||
msgstr "المنطقة"
|
|
||||||
|
|
||||||
#: geo/models.py:183
|
|
||||||
msgid "regions"
|
|
||||||
msgstr "المناطق"
|
|
||||||
|
|
||||||
#: geo/models.py:205
|
|
||||||
msgid "subregion"
|
|
||||||
msgstr "المنطقة الفرعية"
|
|
||||||
|
|
||||||
#: geo/models.py:206
|
|
||||||
msgid "subregions"
|
|
||||||
msgstr "المناطق الفرعية"
|
|
||||||
|
|
||||||
#: geo/models.py:237 geo/models.py:253
|
|
||||||
msgid "city"
|
|
||||||
msgstr "المدينة"
|
|
||||||
|
|
||||||
#: geo/models.py:238 geo/models.py:254
|
|
||||||
msgid "cities"
|
|
||||||
msgstr "المدن"
|
|
||||||
|
|
||||||
#: geo/models.py:270
|
|
||||||
msgid "district"
|
|
||||||
msgstr "المنطقة"
|
|
||||||
|
|
||||||
#: geo/models.py:271
|
|
||||||
msgid "districts"
|
|
||||||
msgstr "المقاطعات"
|
|
||||||
|
|
||||||
#: geo/models.py:344
|
|
||||||
msgid "postal code"
|
|
||||||
msgstr "الرمز البريدي"
|
|
||||||
|
|
||||||
#: geo/models.py:345
|
|
||||||
msgid "postal codes"
|
|
||||||
msgstr "الرموز البريدية"
|
|
||||||
|
|
||||||
#: geo/models.py:391
|
|
||||||
msgid "address"
|
|
||||||
msgstr "العنوان"
|
|
||||||
|
|
||||||
#: geo/models.py:392
|
|
||||||
msgid "addresses"
|
|
||||||
msgstr "العناوين"
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
# eVibes Translations.
|
|
||||||
# Copyright (C) 2025 Egor "fureunoir" Gorbunov
|
|
||||||
# This file is distributed under the same license as the eVibes package.
|
|
||||||
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: 1\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2025-04-28 16:26+0100\n"
|
|
||||||
"PO-Revision-Date: 2025-01-30 03:27+0000\n"
|
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language-Team: CZECH <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language: CZECH\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: geo/apps.py:8
|
|
||||||
msgid "geodata"
|
|
||||||
msgstr "Geodata"
|
|
||||||
|
|
||||||
#: geo/conf.py:407
|
|
||||||
msgid "Name"
|
|
||||||
msgstr "Název"
|
|
||||||
|
|
||||||
#: geo/conf.py:408
|
|
||||||
msgid "Abbreviation"
|
|
||||||
msgstr "Zkratka"
|
|
||||||
|
|
||||||
#: geo/conf.py:409
|
|
||||||
msgid "Link"
|
|
||||||
msgstr "Odkaz na"
|
|
||||||
|
|
||||||
#: geo/conf.py:413
|
|
||||||
msgid "IATA (Airport) Code"
|
|
||||||
msgstr "Kód IATA (letiště)"
|
|
||||||
|
|
||||||
#: geo/conf.py:414
|
|
||||||
msgid "ICAO (Airport) Code"
|
|
||||||
msgstr "Kód ICAO (letiště)"
|
|
||||||
|
|
||||||
#: geo/conf.py:415
|
|
||||||
msgid "FAAC (Airport) Code"
|
|
||||||
msgstr "FAAC (letiště) Kód"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:30
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {city_uuid}"
|
|
||||||
msgstr "{name} neexistuje: {city_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:33
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {postal_code_uuid}"
|
|
||||||
msgstr "{name} neexistuje: {postal_code_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {uuid}"
|
|
||||||
msgstr "{name} neexistuje: {uuid}"
|
|
||||||
|
|
||||||
#: geo/models.py:47
|
|
||||||
msgid "UUID"
|
|
||||||
msgstr "Jedinečné ID"
|
|
||||||
|
|
||||||
#: geo/models.py:48
|
|
||||||
msgid "active"
|
|
||||||
msgstr "Aktivní"
|
|
||||||
|
|
||||||
#: geo/models.py:54
|
|
||||||
msgid "subclasses_of_place_must_implement_slugify"
|
|
||||||
msgstr "Podtřídy třídy `Místo` musí implementovat metodu slugify"
|
|
||||||
|
|
||||||
#: geo/models.py:123
|
|
||||||
msgid "continent"
|
|
||||||
msgstr "Kontinent"
|
|
||||||
|
|
||||||
#: geo/models.py:124
|
|
||||||
msgid "continents"
|
|
||||||
msgstr "Kontinenty"
|
|
||||||
|
|
||||||
#: geo/models.py:149 geo/models.py:169
|
|
||||||
msgid "country"
|
|
||||||
msgstr "Země"
|
|
||||||
|
|
||||||
#: geo/models.py:150 geo/models.py:170
|
|
||||||
msgid "countries"
|
|
||||||
msgstr "Země"
|
|
||||||
|
|
||||||
#: geo/models.py:182
|
|
||||||
msgid "region"
|
|
||||||
msgstr "Region"
|
|
||||||
|
|
||||||
#: geo/models.py:183
|
|
||||||
msgid "regions"
|
|
||||||
msgstr "Regiony"
|
|
||||||
|
|
||||||
#: geo/models.py:205
|
|
||||||
msgid "subregion"
|
|
||||||
msgstr "Subregion"
|
|
||||||
|
|
||||||
#: geo/models.py:206
|
|
||||||
msgid "subregions"
|
|
||||||
msgstr "Subregiony"
|
|
||||||
|
|
||||||
#: geo/models.py:237 geo/models.py:253
|
|
||||||
msgid "city"
|
|
||||||
msgstr "Město"
|
|
||||||
|
|
||||||
#: geo/models.py:238 geo/models.py:254
|
|
||||||
msgid "cities"
|
|
||||||
msgstr "Města"
|
|
||||||
|
|
||||||
#: geo/models.py:270
|
|
||||||
msgid "district"
|
|
||||||
msgstr "Okres"
|
|
||||||
|
|
||||||
#: geo/models.py:271
|
|
||||||
msgid "districts"
|
|
||||||
msgstr "Okresy"
|
|
||||||
|
|
||||||
#: geo/models.py:344
|
|
||||||
msgid "postal code"
|
|
||||||
msgstr "Poštovní směrovací číslo"
|
|
||||||
|
|
||||||
#: geo/models.py:345
|
|
||||||
msgid "postal codes"
|
|
||||||
msgstr "Poštovní směrovací čísla"
|
|
||||||
|
|
||||||
#: geo/models.py:391
|
|
||||||
msgid "address"
|
|
||||||
msgstr "Adresa"
|
|
||||||
|
|
||||||
#: geo/models.py:392
|
|
||||||
msgid "addresses"
|
|
||||||
msgstr "Adresy"
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
# eVibes Translations.
|
|
||||||
# Copyright (C) 2025 Egor "fureunoir" Gorbunov
|
|
||||||
# This file is distributed under the same license as the eVibes package.
|
|
||||||
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: 1\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2025-04-28 16:26+0100\n"
|
|
||||||
"PO-Revision-Date: 2025-01-30 03:27+0000\n"
|
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language-Team: DANISH <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language: DANISH\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: geo/apps.py:8
|
|
||||||
msgid "geodata"
|
|
||||||
msgstr "Geodata"
|
|
||||||
|
|
||||||
#: geo/conf.py:407
|
|
||||||
msgid "Name"
|
|
||||||
msgstr "Navn"
|
|
||||||
|
|
||||||
#: geo/conf.py:408
|
|
||||||
msgid "Abbreviation"
|
|
||||||
msgstr "Forkortelse"
|
|
||||||
|
|
||||||
#: geo/conf.py:409
|
|
||||||
msgid "Link"
|
|
||||||
msgstr "Link til"
|
|
||||||
|
|
||||||
#: geo/conf.py:413
|
|
||||||
msgid "IATA (Airport) Code"
|
|
||||||
msgstr "IATA-kode (lufthavn)"
|
|
||||||
|
|
||||||
#: geo/conf.py:414
|
|
||||||
msgid "ICAO (Airport) Code"
|
|
||||||
msgstr "ICAO-kode (lufthavn)"
|
|
||||||
|
|
||||||
#: geo/conf.py:415
|
|
||||||
msgid "FAAC (Airport) Code"
|
|
||||||
msgstr "FAAC (lufthavn) Kode"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:30
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {city_uuid}"
|
|
||||||
msgstr "{name} findes ikke: {city_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:33
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {postal_code_uuid}"
|
|
||||||
msgstr "{name} findes ikke: {postal_code_uuid}."
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {uuid}"
|
|
||||||
msgstr "{name} findes ikke: {uuid}"
|
|
||||||
|
|
||||||
#: geo/models.py:47
|
|
||||||
msgid "UUID"
|
|
||||||
msgstr "Unikt ID"
|
|
||||||
|
|
||||||
#: geo/models.py:48
|
|
||||||
msgid "active"
|
|
||||||
msgstr "Aktiv"
|
|
||||||
|
|
||||||
#: geo/models.py:54
|
|
||||||
msgid "subclasses_of_place_must_implement_slugify"
|
|
||||||
msgstr "Underklasser af `Place` skal implementere slugify-metoden"
|
|
||||||
|
|
||||||
#: geo/models.py:123
|
|
||||||
msgid "continent"
|
|
||||||
msgstr "Kontinent"
|
|
||||||
|
|
||||||
#: geo/models.py:124
|
|
||||||
msgid "continents"
|
|
||||||
msgstr "Kontinenter"
|
|
||||||
|
|
||||||
#: geo/models.py:149 geo/models.py:169
|
|
||||||
msgid "country"
|
|
||||||
msgstr "Land"
|
|
||||||
|
|
||||||
#: geo/models.py:150 geo/models.py:170
|
|
||||||
msgid "countries"
|
|
||||||
msgstr "Lande"
|
|
||||||
|
|
||||||
#: geo/models.py:182
|
|
||||||
msgid "region"
|
|
||||||
msgstr "Region"
|
|
||||||
|
|
||||||
#: geo/models.py:183
|
|
||||||
msgid "regions"
|
|
||||||
msgstr "Regioner"
|
|
||||||
|
|
||||||
#: geo/models.py:205
|
|
||||||
msgid "subregion"
|
|
||||||
msgstr "Underregion"
|
|
||||||
|
|
||||||
#: geo/models.py:206
|
|
||||||
msgid "subregions"
|
|
||||||
msgstr "Underregioner"
|
|
||||||
|
|
||||||
#: geo/models.py:237 geo/models.py:253
|
|
||||||
msgid "city"
|
|
||||||
msgstr "By"
|
|
||||||
|
|
||||||
#: geo/models.py:238 geo/models.py:254
|
|
||||||
msgid "cities"
|
|
||||||
msgstr "Byer"
|
|
||||||
|
|
||||||
#: geo/models.py:270
|
|
||||||
msgid "district"
|
|
||||||
msgstr "Distrikt"
|
|
||||||
|
|
||||||
#: geo/models.py:271
|
|
||||||
msgid "districts"
|
|
||||||
msgstr "Distrikter"
|
|
||||||
|
|
||||||
#: geo/models.py:344
|
|
||||||
msgid "postal code"
|
|
||||||
msgstr "Postnummer"
|
|
||||||
|
|
||||||
#: geo/models.py:345
|
|
||||||
msgid "postal codes"
|
|
||||||
msgstr "Postnumre"
|
|
||||||
|
|
||||||
#: geo/models.py:391
|
|
||||||
msgid "address"
|
|
||||||
msgstr "Adresse"
|
|
||||||
|
|
||||||
#: geo/models.py:392
|
|
||||||
msgid "addresses"
|
|
||||||
msgstr "Adresser"
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
# eVibes Translations.
|
|
||||||
# Copyright (C) 2025 Egor "fureunoir" Gorbunov
|
|
||||||
# This file is distributed under the same license as the eVibes package.
|
|
||||||
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: 1\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2025-04-28 16:26+0100\n"
|
|
||||||
"PO-Revision-Date: 2025-01-30 03:27+0000\n"
|
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language-Team: BRITISH ENGLISH <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language: BRITISH ENGLISH\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: geo/apps.py:8
|
|
||||||
msgid "geodata"
|
|
||||||
msgstr "Geodaten"
|
|
||||||
|
|
||||||
#: geo/conf.py:407
|
|
||||||
msgid "Name"
|
|
||||||
msgstr "Name"
|
|
||||||
|
|
||||||
#: geo/conf.py:408
|
|
||||||
msgid "Abbreviation"
|
|
||||||
msgstr "Abkürzung"
|
|
||||||
|
|
||||||
#: geo/conf.py:409
|
|
||||||
msgid "Link"
|
|
||||||
msgstr "Link zu"
|
|
||||||
|
|
||||||
#: geo/conf.py:413
|
|
||||||
msgid "IATA (Airport) Code"
|
|
||||||
msgstr "IATA (Flughafen) Code"
|
|
||||||
|
|
||||||
#: geo/conf.py:414
|
|
||||||
msgid "ICAO (Airport) Code"
|
|
||||||
msgstr "ICAO (Flughafen) Code"
|
|
||||||
|
|
||||||
#: geo/conf.py:415
|
|
||||||
msgid "FAAC (Airport) Code"
|
|
||||||
msgstr "FAAC (Flughafen) Code"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:30
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {city_uuid}"
|
|
||||||
msgstr "{name} existiert nicht: {city_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:33
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {postal_code_uuid}"
|
|
||||||
msgstr "{name} existiert nicht: {postal_code_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {uuid}"
|
|
||||||
msgstr "{name} existiert nicht: {uuid}"
|
|
||||||
|
|
||||||
#: geo/models.py:47
|
|
||||||
msgid "UUID"
|
|
||||||
msgstr "Eindeutige ID"
|
|
||||||
|
|
||||||
#: geo/models.py:48
|
|
||||||
msgid "active"
|
|
||||||
msgstr "Aktiv"
|
|
||||||
|
|
||||||
#: geo/models.py:54
|
|
||||||
msgid "subclasses_of_place_must_implement_slugify"
|
|
||||||
msgstr "Unterklassen von `Place` müssen die slugify-Methode implementieren"
|
|
||||||
|
|
||||||
#: geo/models.py:123
|
|
||||||
msgid "continent"
|
|
||||||
msgstr "Kontinent"
|
|
||||||
|
|
||||||
#: geo/models.py:124
|
|
||||||
msgid "continents"
|
|
||||||
msgstr "Kontinente"
|
|
||||||
|
|
||||||
#: geo/models.py:149 geo/models.py:169
|
|
||||||
msgid "country"
|
|
||||||
msgstr "Land"
|
|
||||||
|
|
||||||
#: geo/models.py:150 geo/models.py:170
|
|
||||||
msgid "countries"
|
|
||||||
msgstr "Länder"
|
|
||||||
|
|
||||||
#: geo/models.py:182
|
|
||||||
msgid "region"
|
|
||||||
msgstr "Region"
|
|
||||||
|
|
||||||
#: geo/models.py:183
|
|
||||||
msgid "regions"
|
|
||||||
msgstr "Regionen"
|
|
||||||
|
|
||||||
#: geo/models.py:205
|
|
||||||
msgid "subregion"
|
|
||||||
msgstr "Unterregion"
|
|
||||||
|
|
||||||
#: geo/models.py:206
|
|
||||||
msgid "subregions"
|
|
||||||
msgstr "Teilregionen"
|
|
||||||
|
|
||||||
#: geo/models.py:237 geo/models.py:253
|
|
||||||
msgid "city"
|
|
||||||
msgstr "Stadt"
|
|
||||||
|
|
||||||
#: geo/models.py:238 geo/models.py:254
|
|
||||||
msgid "cities"
|
|
||||||
msgstr "Städte"
|
|
||||||
|
|
||||||
#: geo/models.py:270
|
|
||||||
msgid "district"
|
|
||||||
msgstr "Bezirk"
|
|
||||||
|
|
||||||
#: geo/models.py:271
|
|
||||||
msgid "districts"
|
|
||||||
msgstr "Bezirke"
|
|
||||||
|
|
||||||
#: geo/models.py:344
|
|
||||||
msgid "postal code"
|
|
||||||
msgstr "Postleitzahl"
|
|
||||||
|
|
||||||
#: geo/models.py:345
|
|
||||||
msgid "postal codes"
|
|
||||||
msgstr "Postleitzahlen"
|
|
||||||
|
|
||||||
#: geo/models.py:391
|
|
||||||
msgid "address"
|
|
||||||
msgstr "Adresse"
|
|
||||||
|
|
||||||
#: geo/models.py:392
|
|
||||||
msgid "addresses"
|
|
||||||
msgstr "Adressen"
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
# eVibes Translations.
|
|
||||||
# Copyright (C) 2025 Egor "fureunoir" Gorbunov
|
|
||||||
# This file is distributed under the same license as the eVibes package.
|
|
||||||
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
|
||||||
#
|
|
||||||
# ,fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: 1\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2025-04-28 16:26+0100\n"
|
|
||||||
"PO-Revision-Date: 2025-01-30 03:27+0000\n"
|
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language-Team: BRITISH ENGLISH <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language: BRITISH ENGLISH\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: geo/apps.py:8
|
|
||||||
msgid "geodata"
|
|
||||||
msgstr "Geodata"
|
|
||||||
|
|
||||||
#: geo/conf.py:407
|
|
||||||
msgid "Name"
|
|
||||||
msgstr "Name"
|
|
||||||
|
|
||||||
#: geo/conf.py:408
|
|
||||||
msgid "Abbreviation"
|
|
||||||
msgstr "Abbreviation"
|
|
||||||
|
|
||||||
#: geo/conf.py:409
|
|
||||||
msgid "Link"
|
|
||||||
msgstr "Link"
|
|
||||||
|
|
||||||
#: geo/conf.py:413
|
|
||||||
msgid "IATA (Airport) Code"
|
|
||||||
msgstr "IATA (Airport) Code"
|
|
||||||
|
|
||||||
#: geo/conf.py:414
|
|
||||||
msgid "ICAO (Airport) Code"
|
|
||||||
msgstr "ICAO (Airport) Code"
|
|
||||||
|
|
||||||
#: geo/conf.py:415
|
|
||||||
msgid "FAAC (Airport) Code"
|
|
||||||
msgstr "FAAC (Airport) Code"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:30
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {city_uuid}"
|
|
||||||
msgstr "{name} does not exist: {city_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:33
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {postal_code_uuid}"
|
|
||||||
msgstr "{name} does not exist: {postal_code_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {uuid}"
|
|
||||||
msgstr "{name} does not exist: {uuid}"
|
|
||||||
|
|
||||||
#: geo/models.py:47
|
|
||||||
msgid "UUID"
|
|
||||||
msgstr "Unique ID"
|
|
||||||
|
|
||||||
#: geo/models.py:48
|
|
||||||
msgid "active"
|
|
||||||
msgstr "Active"
|
|
||||||
|
|
||||||
#: geo/models.py:54
|
|
||||||
msgid "subclasses_of_place_must_implement_slugify"
|
|
||||||
msgstr "Subclasses of `Place` must implement slugify method"
|
|
||||||
|
|
||||||
#: geo/models.py:123
|
|
||||||
msgid "continent"
|
|
||||||
msgstr "Continent"
|
|
||||||
|
|
||||||
#: geo/models.py:124
|
|
||||||
msgid "continents"
|
|
||||||
msgstr "Continents"
|
|
||||||
|
|
||||||
#: geo/models.py:149 geo/models.py:169
|
|
||||||
msgid "country"
|
|
||||||
msgstr "Country"
|
|
||||||
|
|
||||||
#: geo/models.py:150 geo/models.py:170
|
|
||||||
msgid "countries"
|
|
||||||
msgstr "Countries"
|
|
||||||
|
|
||||||
#: geo/models.py:182
|
|
||||||
msgid "region"
|
|
||||||
msgstr "Region"
|
|
||||||
|
|
||||||
#: geo/models.py:183
|
|
||||||
msgid "regions"
|
|
||||||
msgstr "Regions"
|
|
||||||
|
|
||||||
#: geo/models.py:205
|
|
||||||
msgid "subregion"
|
|
||||||
msgstr "Subregion"
|
|
||||||
|
|
||||||
#: geo/models.py:206
|
|
||||||
msgid "subregions"
|
|
||||||
msgstr "Subregions"
|
|
||||||
|
|
||||||
#: geo/models.py:237 geo/models.py:253
|
|
||||||
msgid "city"
|
|
||||||
msgstr "City"
|
|
||||||
|
|
||||||
#: geo/models.py:238 geo/models.py:254
|
|
||||||
msgid "cities"
|
|
||||||
msgstr "Cities"
|
|
||||||
|
|
||||||
#: geo/models.py:270
|
|
||||||
msgid "district"
|
|
||||||
msgstr "District"
|
|
||||||
|
|
||||||
#: geo/models.py:271
|
|
||||||
msgid "districts"
|
|
||||||
msgstr "Districts"
|
|
||||||
|
|
||||||
#: geo/models.py:344
|
|
||||||
msgid "postal code"
|
|
||||||
msgstr "Postal code"
|
|
||||||
|
|
||||||
#: geo/models.py:345
|
|
||||||
msgid "postal codes"
|
|
||||||
msgstr "Postal codes"
|
|
||||||
|
|
||||||
#: geo/models.py:391
|
|
||||||
msgid "address"
|
|
||||||
msgstr "Address"
|
|
||||||
|
|
||||||
#: geo/models.py:392
|
|
||||||
msgid "addresses"
|
|
||||||
msgstr "Addresses"
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
# eVibes Translations.
|
|
||||||
# Copyright (C) 2025 Egor "fureunoir" Gorbunov
|
|
||||||
# This file is distributed under the same license as the eVibes package.
|
|
||||||
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: 1\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2025-04-28 16:26+0100\n"
|
|
||||||
"PO-Revision-Date: 2025-01-30 03:27+0000\n"
|
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language-Team: BRITISH ENGLISH <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language: BRITISH ENGLISH\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: geo/apps.py:8
|
|
||||||
msgid "geodata"
|
|
||||||
msgstr "Geodata"
|
|
||||||
|
|
||||||
#: geo/conf.py:407
|
|
||||||
msgid "Name"
|
|
||||||
msgstr "Name"
|
|
||||||
|
|
||||||
#: geo/conf.py:408
|
|
||||||
msgid "Abbreviation"
|
|
||||||
msgstr "Abbreviation"
|
|
||||||
|
|
||||||
#: geo/conf.py:409
|
|
||||||
msgid "Link"
|
|
||||||
msgstr "Link to"
|
|
||||||
|
|
||||||
#: geo/conf.py:413
|
|
||||||
msgid "IATA (Airport) Code"
|
|
||||||
msgstr "IATA (Airport) Code"
|
|
||||||
|
|
||||||
#: geo/conf.py:414
|
|
||||||
msgid "ICAO (Airport) Code"
|
|
||||||
msgstr "ICAO (Airport) Code"
|
|
||||||
|
|
||||||
#: geo/conf.py:415
|
|
||||||
msgid "FAAC (Airport) Code"
|
|
||||||
msgstr "FAAC (Airport) Code"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:30
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {city_uuid}"
|
|
||||||
msgstr "{name} does not exist: {city_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:33
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {postal_code_uuid}"
|
|
||||||
msgstr "{name} does not exist: {postal_code_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {uuid}"
|
|
||||||
msgstr "{name} does not exist: {uuid}"
|
|
||||||
|
|
||||||
#: geo/models.py:47
|
|
||||||
msgid "UUID"
|
|
||||||
msgstr "Unique ID"
|
|
||||||
|
|
||||||
#: geo/models.py:48
|
|
||||||
msgid "active"
|
|
||||||
msgstr "Active"
|
|
||||||
|
|
||||||
#: geo/models.py:54
|
|
||||||
msgid "subclasses_of_place_must_implement_slugify"
|
|
||||||
msgstr "Subclasses of `Place` must implement slugify method"
|
|
||||||
|
|
||||||
#: geo/models.py:123
|
|
||||||
msgid "continent"
|
|
||||||
msgstr "Continent"
|
|
||||||
|
|
||||||
#: geo/models.py:124
|
|
||||||
msgid "continents"
|
|
||||||
msgstr "Continents"
|
|
||||||
|
|
||||||
#: geo/models.py:149 geo/models.py:169
|
|
||||||
msgid "country"
|
|
||||||
msgstr "Country"
|
|
||||||
|
|
||||||
#: geo/models.py:150 geo/models.py:170
|
|
||||||
msgid "countries"
|
|
||||||
msgstr "Countries"
|
|
||||||
|
|
||||||
#: geo/models.py:182
|
|
||||||
msgid "region"
|
|
||||||
msgstr "Region"
|
|
||||||
|
|
||||||
#: geo/models.py:183
|
|
||||||
msgid "regions"
|
|
||||||
msgstr "Regions"
|
|
||||||
|
|
||||||
#: geo/models.py:205
|
|
||||||
msgid "subregion"
|
|
||||||
msgstr "Subregion"
|
|
||||||
|
|
||||||
#: geo/models.py:206
|
|
||||||
msgid "subregions"
|
|
||||||
msgstr "Subregions"
|
|
||||||
|
|
||||||
#: geo/models.py:237 geo/models.py:253
|
|
||||||
msgid "city"
|
|
||||||
msgstr "City"
|
|
||||||
|
|
||||||
#: geo/models.py:238 geo/models.py:254
|
|
||||||
msgid "cities"
|
|
||||||
msgstr "Cities"
|
|
||||||
|
|
||||||
#: geo/models.py:270
|
|
||||||
msgid "district"
|
|
||||||
msgstr "District"
|
|
||||||
|
|
||||||
#: geo/models.py:271
|
|
||||||
msgid "districts"
|
|
||||||
msgstr "Districts"
|
|
||||||
|
|
||||||
#: geo/models.py:344
|
|
||||||
msgid "postal code"
|
|
||||||
msgstr "Postal code"
|
|
||||||
|
|
||||||
#: geo/models.py:345
|
|
||||||
msgid "postal codes"
|
|
||||||
msgstr "Postal codes"
|
|
||||||
|
|
||||||
#: geo/models.py:391
|
|
||||||
msgid "address"
|
|
||||||
msgstr "Address"
|
|
||||||
|
|
||||||
#: geo/models.py:392
|
|
||||||
msgid "addresses"
|
|
||||||
msgstr "Addresses"
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
# eVibes Translations.
|
|
||||||
# Copyright (C) 2025 Egor "fureunoir" Gorbunov
|
|
||||||
# This file is distributed under the same license as the eVibes package.
|
|
||||||
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: 1\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2025-04-28 16:26+0100\n"
|
|
||||||
"PO-Revision-Date: 2025-01-30 03:27+0000\n"
|
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language-Team: SPANISH <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language: SPANISH\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: geo/apps.py:8
|
|
||||||
msgid "geodata"
|
|
||||||
msgstr "Geodatos"
|
|
||||||
|
|
||||||
#: geo/conf.py:407
|
|
||||||
msgid "Name"
|
|
||||||
msgstr "Nombre"
|
|
||||||
|
|
||||||
#: geo/conf.py:408
|
|
||||||
msgid "Abbreviation"
|
|
||||||
msgstr "Abreviatura"
|
|
||||||
|
|
||||||
#: geo/conf.py:409
|
|
||||||
msgid "Link"
|
|
||||||
msgstr "Enlace"
|
|
||||||
|
|
||||||
#: geo/conf.py:413
|
|
||||||
msgid "IATA (Airport) Code"
|
|
||||||
msgstr "Código IATA (aeropuerto)"
|
|
||||||
|
|
||||||
#: geo/conf.py:414
|
|
||||||
msgid "ICAO (Airport) Code"
|
|
||||||
msgstr "Código OACI (Aeropuerto)"
|
|
||||||
|
|
||||||
#: geo/conf.py:415
|
|
||||||
msgid "FAAC (Airport) Code"
|
|
||||||
msgstr "FAAC (Aeropuerto) Código"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:30
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {city_uuid}"
|
|
||||||
msgstr "{name} no existe: {city_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:33
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {postal_code_uuid}"
|
|
||||||
msgstr "{name} no existe: {postal_code_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {uuid}"
|
|
||||||
msgstr "{name} no existe: {uuid}"
|
|
||||||
|
|
||||||
#: geo/models.py:47
|
|
||||||
msgid "UUID"
|
|
||||||
msgstr "Identificación única"
|
|
||||||
|
|
||||||
#: geo/models.py:48
|
|
||||||
msgid "active"
|
|
||||||
msgstr "Activo"
|
|
||||||
|
|
||||||
#: geo/models.py:54
|
|
||||||
msgid "subclasses_of_place_must_implement_slugify"
|
|
||||||
msgstr "Las subclases de `Place` deben implementar el método slugify"
|
|
||||||
|
|
||||||
#: geo/models.py:123
|
|
||||||
msgid "continent"
|
|
||||||
msgstr "Continente"
|
|
||||||
|
|
||||||
#: geo/models.py:124
|
|
||||||
msgid "continents"
|
|
||||||
msgstr "Continentes"
|
|
||||||
|
|
||||||
#: geo/models.py:149 geo/models.py:169
|
|
||||||
msgid "country"
|
|
||||||
msgstr "País"
|
|
||||||
|
|
||||||
#: geo/models.py:150 geo/models.py:170
|
|
||||||
msgid "countries"
|
|
||||||
msgstr "Países"
|
|
||||||
|
|
||||||
#: geo/models.py:182
|
|
||||||
msgid "region"
|
|
||||||
msgstr "Región"
|
|
||||||
|
|
||||||
#: geo/models.py:183
|
|
||||||
msgid "regions"
|
|
||||||
msgstr "Regiones"
|
|
||||||
|
|
||||||
#: geo/models.py:205
|
|
||||||
msgid "subregion"
|
|
||||||
msgstr "Subregion"
|
|
||||||
|
|
||||||
#: geo/models.py:206
|
|
||||||
msgid "subregions"
|
|
||||||
msgstr "Subregiones"
|
|
||||||
|
|
||||||
#: geo/models.py:237 geo/models.py:253
|
|
||||||
msgid "city"
|
|
||||||
msgstr "Ciudad"
|
|
||||||
|
|
||||||
#: geo/models.py:238 geo/models.py:254
|
|
||||||
msgid "cities"
|
|
||||||
msgstr "Ciudades"
|
|
||||||
|
|
||||||
#: geo/models.py:270
|
|
||||||
msgid "district"
|
|
||||||
msgstr "Distrito"
|
|
||||||
|
|
||||||
#: geo/models.py:271
|
|
||||||
msgid "districts"
|
|
||||||
msgstr "Distritos"
|
|
||||||
|
|
||||||
#: geo/models.py:344
|
|
||||||
msgid "postal code"
|
|
||||||
msgstr "Código postal"
|
|
||||||
|
|
||||||
#: geo/models.py:345
|
|
||||||
msgid "postal codes"
|
|
||||||
msgstr "Códigos postales"
|
|
||||||
|
|
||||||
#: geo/models.py:391
|
|
||||||
msgid "address"
|
|
||||||
msgstr "Dirección"
|
|
||||||
|
|
||||||
#: geo/models.py:392
|
|
||||||
msgid "addresses"
|
|
||||||
msgstr "Direcciones"
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
# eVibes Translations.
|
|
||||||
# Copyright (C) 2025 Egor "fureunoir" Gorbunov
|
|
||||||
# This file is distributed under the same license as the eVibes package.
|
|
||||||
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: 1\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2025-04-28 16:26+0100\n"
|
|
||||||
"PO-Revision-Date: 2025-01-30 03:27+0000\n"
|
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language-Team: BRITISH ENGLISH <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language: BRITISH ENGLISH\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: geo/apps.py:8
|
|
||||||
msgid "geodata"
|
|
||||||
msgstr "Géodonnées"
|
|
||||||
|
|
||||||
#: geo/conf.py:407
|
|
||||||
msgid "Name"
|
|
||||||
msgstr "Nom"
|
|
||||||
|
|
||||||
#: geo/conf.py:408
|
|
||||||
msgid "Abbreviation"
|
|
||||||
msgstr "Abréviation"
|
|
||||||
|
|
||||||
#: geo/conf.py:409
|
|
||||||
msgid "Link"
|
|
||||||
msgstr "Lien vers"
|
|
||||||
|
|
||||||
#: geo/conf.py:413
|
|
||||||
msgid "IATA (Airport) Code"
|
|
||||||
msgstr "Code IATA (aéroport)"
|
|
||||||
|
|
||||||
#: geo/conf.py:414
|
|
||||||
msgid "ICAO (Airport) Code"
|
|
||||||
msgstr "Code OACI (aéroport)"
|
|
||||||
|
|
||||||
#: geo/conf.py:415
|
|
||||||
msgid "FAAC (Airport) Code"
|
|
||||||
msgstr "Code FAAC (Aéroport)"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:30
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {city_uuid}"
|
|
||||||
msgstr "{name} n'existe pas : {city_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:33
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {postal_code_uuid}"
|
|
||||||
msgstr "{name} n'existe pas : {postal_code_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {uuid}"
|
|
||||||
msgstr "{name} n'existe pas : {uuid}"
|
|
||||||
|
|
||||||
#: geo/models.py:47
|
|
||||||
msgid "UUID"
|
|
||||||
msgstr "Unique ID"
|
|
||||||
|
|
||||||
#: geo/models.py:48
|
|
||||||
msgid "active"
|
|
||||||
msgstr "Actif"
|
|
||||||
|
|
||||||
#: geo/models.py:54
|
|
||||||
msgid "subclasses_of_place_must_implement_slugify"
|
|
||||||
msgstr "Les sous-classes de `Place` doivent implémenter la méthode slugify"
|
|
||||||
|
|
||||||
#: geo/models.py:123
|
|
||||||
msgid "continent"
|
|
||||||
msgstr "Continent"
|
|
||||||
|
|
||||||
#: geo/models.py:124
|
|
||||||
msgid "continents"
|
|
||||||
msgstr "Continents"
|
|
||||||
|
|
||||||
#: geo/models.py:149 geo/models.py:169
|
|
||||||
msgid "country"
|
|
||||||
msgstr "Pays"
|
|
||||||
|
|
||||||
#: geo/models.py:150 geo/models.py:170
|
|
||||||
msgid "countries"
|
|
||||||
msgstr "Pays"
|
|
||||||
|
|
||||||
#: geo/models.py:182
|
|
||||||
msgid "region"
|
|
||||||
msgstr "Région"
|
|
||||||
|
|
||||||
#: geo/models.py:183
|
|
||||||
msgid "regions"
|
|
||||||
msgstr "Régions"
|
|
||||||
|
|
||||||
#: geo/models.py:205
|
|
||||||
msgid "subregion"
|
|
||||||
msgstr "Sous-région"
|
|
||||||
|
|
||||||
#: geo/models.py:206
|
|
||||||
msgid "subregions"
|
|
||||||
msgstr "Sous-régions"
|
|
||||||
|
|
||||||
#: geo/models.py:237 geo/models.py:253
|
|
||||||
msgid "city"
|
|
||||||
msgstr "Ville"
|
|
||||||
|
|
||||||
#: geo/models.py:238 geo/models.py:254
|
|
||||||
msgid "cities"
|
|
||||||
msgstr "Villes"
|
|
||||||
|
|
||||||
#: geo/models.py:270
|
|
||||||
msgid "district"
|
|
||||||
msgstr "District"
|
|
||||||
|
|
||||||
#: geo/models.py:271
|
|
||||||
msgid "districts"
|
|
||||||
msgstr "Districts"
|
|
||||||
|
|
||||||
#: geo/models.py:344
|
|
||||||
msgid "postal code"
|
|
||||||
msgstr "Code postal"
|
|
||||||
|
|
||||||
#: geo/models.py:345
|
|
||||||
msgid "postal codes"
|
|
||||||
msgstr "Codes postaux"
|
|
||||||
|
|
||||||
#: geo/models.py:391
|
|
||||||
msgid "address"
|
|
||||||
msgstr "Adresse"
|
|
||||||
|
|
||||||
#: geo/models.py:392
|
|
||||||
msgid "addresses"
|
|
||||||
msgstr "Adresses"
|
|
||||||
|
|
@ -1,137 +0,0 @@
|
||||||
# SOME DESCRIPTIVE TITLE.
|
|
||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2025-04-28 16:26+0100\n"
|
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
||||||
"Language: \n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
|
|
||||||
#: geo/apps.py:8
|
|
||||||
msgid "geodata"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/conf.py:407
|
|
||||||
msgid "Name"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/conf.py:408
|
|
||||||
msgid "Abbreviation"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/conf.py:409
|
|
||||||
msgid "Link"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/conf.py:413
|
|
||||||
msgid "IATA (Airport) Code"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/conf.py:414
|
|
||||||
msgid "ICAO (Airport) Code"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/conf.py:415
|
|
||||||
msgid "FAAC (Airport) Code"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:30
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {city_uuid}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:33
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {postal_code_uuid}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {uuid}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:47
|
|
||||||
msgid "UUID"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:48
|
|
||||||
msgid "active"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:54
|
|
||||||
msgid "subclasses_of_place_must_implement_slugify"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:123
|
|
||||||
msgid "continent"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:124
|
|
||||||
msgid "continents"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:149 geo/models.py:169
|
|
||||||
msgid "country"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:150 geo/models.py:170
|
|
||||||
msgid "countries"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:182
|
|
||||||
msgid "region"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:183
|
|
||||||
msgid "regions"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:205
|
|
||||||
msgid "subregion"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:206
|
|
||||||
msgid "subregions"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:237 geo/models.py:253
|
|
||||||
msgid "city"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:238 geo/models.py:254
|
|
||||||
msgid "cities"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:270
|
|
||||||
msgid "district"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:271
|
|
||||||
msgid "districts"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:344
|
|
||||||
msgid "postal code"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:345
|
|
||||||
msgid "postal codes"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:391
|
|
||||||
msgid "address"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:392
|
|
||||||
msgid "addresses"
|
|
||||||
msgstr ""
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
# eVibes Translations.
|
|
||||||
# Copyright (C) 2025 Egor "fureunoir" Gorbunov
|
|
||||||
# This file is distributed under the same license as the eVibes package.
|
|
||||||
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: 1\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2025-04-28 16:26+0100\n"
|
|
||||||
"PO-Revision-Date: 2025-01-30 03:27+0000\n"
|
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language-Team: ITALIAN <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language: ITALIAN\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: geo/apps.py:8
|
|
||||||
msgid "geodata"
|
|
||||||
msgstr "Geodati"
|
|
||||||
|
|
||||||
#: geo/conf.py:407
|
|
||||||
msgid "Name"
|
|
||||||
msgstr "Nome"
|
|
||||||
|
|
||||||
#: geo/conf.py:408
|
|
||||||
msgid "Abbreviation"
|
|
||||||
msgstr "Abbreviazione"
|
|
||||||
|
|
||||||
#: geo/conf.py:409
|
|
||||||
msgid "Link"
|
|
||||||
msgstr "Collegamento a"
|
|
||||||
|
|
||||||
#: geo/conf.py:413
|
|
||||||
msgid "IATA (Airport) Code"
|
|
||||||
msgstr "IATA (Airport) Code"
|
|
||||||
|
|
||||||
#: geo/conf.py:414
|
|
||||||
msgid "ICAO (Airport) Code"
|
|
||||||
msgstr "ICAO (Airport) Code"
|
|
||||||
|
|
||||||
#: geo/conf.py:415
|
|
||||||
msgid "FAAC (Airport) Code"
|
|
||||||
msgstr "Codice FAAC (Aeroporto)"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:30
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {city_uuid}"
|
|
||||||
msgstr "{name} non esiste: {city_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:33
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {postal_code_uuid}"
|
|
||||||
msgstr "{name} non esiste: {postal_code_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {uuid}"
|
|
||||||
msgstr "{name} non esiste: {uuid}"
|
|
||||||
|
|
||||||
#: geo/models.py:47
|
|
||||||
msgid "UUID"
|
|
||||||
msgstr "ID univoco"
|
|
||||||
|
|
||||||
#: geo/models.py:48
|
|
||||||
msgid "active"
|
|
||||||
msgstr "Attivo"
|
|
||||||
|
|
||||||
#: geo/models.py:54
|
|
||||||
msgid "subclasses_of_place_must_implement_slugify"
|
|
||||||
msgstr "Le sottoclassi di `Place` devono implementare il metodo slugify"
|
|
||||||
|
|
||||||
#: geo/models.py:123
|
|
||||||
msgid "continent"
|
|
||||||
msgstr "Continente"
|
|
||||||
|
|
||||||
#: geo/models.py:124
|
|
||||||
msgid "continents"
|
|
||||||
msgstr "Continenti"
|
|
||||||
|
|
||||||
#: geo/models.py:149 geo/models.py:169
|
|
||||||
msgid "country"
|
|
||||||
msgstr "Paese"
|
|
||||||
|
|
||||||
#: geo/models.py:150 geo/models.py:170
|
|
||||||
msgid "countries"
|
|
||||||
msgstr "Paesi"
|
|
||||||
|
|
||||||
#: geo/models.py:182
|
|
||||||
msgid "region"
|
|
||||||
msgstr "Regione"
|
|
||||||
|
|
||||||
#: geo/models.py:183
|
|
||||||
msgid "regions"
|
|
||||||
msgstr "Regioni"
|
|
||||||
|
|
||||||
#: geo/models.py:205
|
|
||||||
msgid "subregion"
|
|
||||||
msgstr "Sottoregione"
|
|
||||||
|
|
||||||
#: geo/models.py:206
|
|
||||||
msgid "subregions"
|
|
||||||
msgstr "Sottoregioni"
|
|
||||||
|
|
||||||
#: geo/models.py:237 geo/models.py:253
|
|
||||||
msgid "city"
|
|
||||||
msgstr "Città"
|
|
||||||
|
|
||||||
#: geo/models.py:238 geo/models.py:254
|
|
||||||
msgid "cities"
|
|
||||||
msgstr "Città"
|
|
||||||
|
|
||||||
#: geo/models.py:270
|
|
||||||
msgid "district"
|
|
||||||
msgstr "Distretto"
|
|
||||||
|
|
||||||
#: geo/models.py:271
|
|
||||||
msgid "districts"
|
|
||||||
msgstr "Distretti"
|
|
||||||
|
|
||||||
#: geo/models.py:344
|
|
||||||
msgid "postal code"
|
|
||||||
msgstr "Codice postale"
|
|
||||||
|
|
||||||
#: geo/models.py:345
|
|
||||||
msgid "postal codes"
|
|
||||||
msgstr "Codici postali"
|
|
||||||
|
|
||||||
#: geo/models.py:391
|
|
||||||
msgid "address"
|
|
||||||
msgstr "Indirizzo"
|
|
||||||
|
|
||||||
#: geo/models.py:392
|
|
||||||
msgid "addresses"
|
|
||||||
msgstr "Indirizzi"
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
# eVibes Translations.
|
|
||||||
# Copyright (C) 2025 Egor "fureunoir" Gorbunov
|
|
||||||
# This file is distributed under the same license as the eVibes package.
|
|
||||||
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: 1\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2025-04-28 16:26+0100\n"
|
|
||||||
"PO-Revision-Date: 2025-01-30 03:27+0000\n"
|
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language-Team: BRITISH ENGLISH <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language: BRITISH ENGLISH\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: geo/apps.py:8
|
|
||||||
msgid "geodata"
|
|
||||||
msgstr "ジオデータ"
|
|
||||||
|
|
||||||
#: geo/conf.py:407
|
|
||||||
msgid "Name"
|
|
||||||
msgstr "名称"
|
|
||||||
|
|
||||||
#: geo/conf.py:408
|
|
||||||
msgid "Abbreviation"
|
|
||||||
msgstr "略語"
|
|
||||||
|
|
||||||
#: geo/conf.py:409
|
|
||||||
msgid "Link"
|
|
||||||
msgstr "リンク"
|
|
||||||
|
|
||||||
#: geo/conf.py:413
|
|
||||||
msgid "IATA (Airport) Code"
|
|
||||||
msgstr "IATA(空港)コード"
|
|
||||||
|
|
||||||
#: geo/conf.py:414
|
|
||||||
msgid "ICAO (Airport) Code"
|
|
||||||
msgstr "ICAO(空港)コード"
|
|
||||||
|
|
||||||
#: geo/conf.py:415
|
|
||||||
msgid "FAAC (Airport) Code"
|
|
||||||
msgstr "FAAC (空港) コード"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:30
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {city_uuid}"
|
|
||||||
msgstr "{name}が存在しません:{city_uuid}が存在しません。"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:33
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {postal_code_uuid}"
|
|
||||||
msgstr "{name}が存在しません:{postal_code_uuid}が存在しません。"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {uuid}"
|
|
||||||
msgstr "{name}が存在しません:{uuid}"
|
|
||||||
|
|
||||||
#: geo/models.py:47
|
|
||||||
msgid "UUID"
|
|
||||||
msgstr "ユニークID"
|
|
||||||
|
|
||||||
#: geo/models.py:48
|
|
||||||
msgid "active"
|
|
||||||
msgstr "アクティブ"
|
|
||||||
|
|
||||||
#: geo/models.py:54
|
|
||||||
msgid "subclasses_of_place_must_implement_slugify"
|
|
||||||
msgstr "Place` のサブクラスは slugify メソッドを実装しなければならない。"
|
|
||||||
|
|
||||||
#: geo/models.py:123
|
|
||||||
msgid "continent"
|
|
||||||
msgstr "大陸"
|
|
||||||
|
|
||||||
#: geo/models.py:124
|
|
||||||
msgid "continents"
|
|
||||||
msgstr "大陸"
|
|
||||||
|
|
||||||
#: geo/models.py:149 geo/models.py:169
|
|
||||||
msgid "country"
|
|
||||||
msgstr "国名"
|
|
||||||
|
|
||||||
#: geo/models.py:150 geo/models.py:170
|
|
||||||
msgid "countries"
|
|
||||||
msgstr "国名"
|
|
||||||
|
|
||||||
#: geo/models.py:182
|
|
||||||
msgid "region"
|
|
||||||
msgstr "地域"
|
|
||||||
|
|
||||||
#: geo/models.py:183
|
|
||||||
msgid "regions"
|
|
||||||
msgstr "地域"
|
|
||||||
|
|
||||||
#: geo/models.py:205
|
|
||||||
msgid "subregion"
|
|
||||||
msgstr "サブリージョン"
|
|
||||||
|
|
||||||
#: geo/models.py:206
|
|
||||||
msgid "subregions"
|
|
||||||
msgstr "サブリージョン"
|
|
||||||
|
|
||||||
#: geo/models.py:237 geo/models.py:253
|
|
||||||
msgid "city"
|
|
||||||
msgstr "都市"
|
|
||||||
|
|
||||||
#: geo/models.py:238 geo/models.py:254
|
|
||||||
msgid "cities"
|
|
||||||
msgstr "都市"
|
|
||||||
|
|
||||||
#: geo/models.py:270
|
|
||||||
msgid "district"
|
|
||||||
msgstr "地区"
|
|
||||||
|
|
||||||
#: geo/models.py:271
|
|
||||||
msgid "districts"
|
|
||||||
msgstr "地区"
|
|
||||||
|
|
||||||
#: geo/models.py:344
|
|
||||||
msgid "postal code"
|
|
||||||
msgstr "郵便番号"
|
|
||||||
|
|
||||||
#: geo/models.py:345
|
|
||||||
msgid "postal codes"
|
|
||||||
msgstr "郵便番号"
|
|
||||||
|
|
||||||
#: geo/models.py:391
|
|
||||||
msgid "address"
|
|
||||||
msgstr "住所"
|
|
||||||
|
|
||||||
#: geo/models.py:392
|
|
||||||
msgid "addresses"
|
|
||||||
msgstr "住所"
|
|
||||||
|
|
@ -1,137 +0,0 @@
|
||||||
# SOME DESCRIPTIVE TITLE.
|
|
||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2025-04-28 16:26+0100\n"
|
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
||||||
"Language: \n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
|
|
||||||
#: geo/apps.py:8
|
|
||||||
msgid "geodata"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/conf.py:407
|
|
||||||
msgid "Name"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/conf.py:408
|
|
||||||
msgid "Abbreviation"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/conf.py:409
|
|
||||||
msgid "Link"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/conf.py:413
|
|
||||||
msgid "IATA (Airport) Code"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/conf.py:414
|
|
||||||
msgid "ICAO (Airport) Code"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/conf.py:415
|
|
||||||
msgid "FAAC (Airport) Code"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:30
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {city_uuid}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:33
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {postal_code_uuid}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {uuid}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:47
|
|
||||||
msgid "UUID"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:48
|
|
||||||
msgid "active"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:54
|
|
||||||
msgid "subclasses_of_place_must_implement_slugify"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:123
|
|
||||||
msgid "continent"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:124
|
|
||||||
msgid "continents"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:149 geo/models.py:169
|
|
||||||
msgid "country"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:150 geo/models.py:170
|
|
||||||
msgid "countries"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:182
|
|
||||||
msgid "region"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:183
|
|
||||||
msgid "regions"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:205
|
|
||||||
msgid "subregion"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:206
|
|
||||||
msgid "subregions"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:237 geo/models.py:253
|
|
||||||
msgid "city"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:238 geo/models.py:254
|
|
||||||
msgid "cities"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:270
|
|
||||||
msgid "district"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:271
|
|
||||||
msgid "districts"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:344
|
|
||||||
msgid "postal code"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:345
|
|
||||||
msgid "postal codes"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:391
|
|
||||||
msgid "address"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: geo/models.py:392
|
|
||||||
msgid "addresses"
|
|
||||||
msgstr ""
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
# eVibes Translations.
|
|
||||||
# Copyright (C) 2025 Egor "fureunoir" Gorbunov
|
|
||||||
# This file is distributed under the same license as the eVibes package.
|
|
||||||
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: 1\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2025-04-28 16:26+0100\n"
|
|
||||||
"PO-Revision-Date: 2025-01-30 03:27+0000\n"
|
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language-Team: DUTCH <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language: DUTCH\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: geo/apps.py:8
|
|
||||||
msgid "geodata"
|
|
||||||
msgstr "Geodata"
|
|
||||||
|
|
||||||
#: geo/conf.py:407
|
|
||||||
msgid "Name"
|
|
||||||
msgstr "Naam"
|
|
||||||
|
|
||||||
#: geo/conf.py:408
|
|
||||||
msgid "Abbreviation"
|
|
||||||
msgstr "Afkorting"
|
|
||||||
|
|
||||||
#: geo/conf.py:409
|
|
||||||
msgid "Link"
|
|
||||||
msgstr "Koppeling naar"
|
|
||||||
|
|
||||||
#: geo/conf.py:413
|
|
||||||
msgid "IATA (Airport) Code"
|
|
||||||
msgstr "IATA (Luchthaven) Code"
|
|
||||||
|
|
||||||
#: geo/conf.py:414
|
|
||||||
msgid "ICAO (Airport) Code"
|
|
||||||
msgstr "ICAO (Luchthaven) Code"
|
|
||||||
|
|
||||||
#: geo/conf.py:415
|
|
||||||
msgid "FAAC (Airport) Code"
|
|
||||||
msgstr "FAAC (Luchthaven) Code"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:30
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {city_uuid}"
|
|
||||||
msgstr "{name} bestaat niet: {city_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:33
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {postal_code_uuid}"
|
|
||||||
msgstr "{name} bestaat niet: {postal_code_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {uuid}"
|
|
||||||
msgstr "{name} bestaat niet: {uuid}"
|
|
||||||
|
|
||||||
#: geo/models.py:47
|
|
||||||
msgid "UUID"
|
|
||||||
msgstr "Uniek ID"
|
|
||||||
|
|
||||||
#: geo/models.py:48
|
|
||||||
msgid "active"
|
|
||||||
msgstr "Actief"
|
|
||||||
|
|
||||||
#: geo/models.py:54
|
|
||||||
msgid "subclasses_of_place_must_implement_slugify"
|
|
||||||
msgstr "Subklassen van `Place` moeten de methode slugify implementeren"
|
|
||||||
|
|
||||||
#: geo/models.py:123
|
|
||||||
msgid "continent"
|
|
||||||
msgstr "Continent"
|
|
||||||
|
|
||||||
#: geo/models.py:124
|
|
||||||
msgid "continents"
|
|
||||||
msgstr "Continenten"
|
|
||||||
|
|
||||||
#: geo/models.py:149 geo/models.py:169
|
|
||||||
msgid "country"
|
|
||||||
msgstr "Land"
|
|
||||||
|
|
||||||
#: geo/models.py:150 geo/models.py:170
|
|
||||||
msgid "countries"
|
|
||||||
msgstr "Landen"
|
|
||||||
|
|
||||||
#: geo/models.py:182
|
|
||||||
msgid "region"
|
|
||||||
msgstr "Regio"
|
|
||||||
|
|
||||||
#: geo/models.py:183
|
|
||||||
msgid "regions"
|
|
||||||
msgstr "Regio's"
|
|
||||||
|
|
||||||
#: geo/models.py:205
|
|
||||||
msgid "subregion"
|
|
||||||
msgstr "Subregio"
|
|
||||||
|
|
||||||
#: geo/models.py:206
|
|
||||||
msgid "subregions"
|
|
||||||
msgstr "Subregio's"
|
|
||||||
|
|
||||||
#: geo/models.py:237 geo/models.py:253
|
|
||||||
msgid "city"
|
|
||||||
msgstr "Stad"
|
|
||||||
|
|
||||||
#: geo/models.py:238 geo/models.py:254
|
|
||||||
msgid "cities"
|
|
||||||
msgstr "Steden"
|
|
||||||
|
|
||||||
#: geo/models.py:270
|
|
||||||
msgid "district"
|
|
||||||
msgstr "District"
|
|
||||||
|
|
||||||
#: geo/models.py:271
|
|
||||||
msgid "districts"
|
|
||||||
msgstr "Wijken"
|
|
||||||
|
|
||||||
#: geo/models.py:344
|
|
||||||
msgid "postal code"
|
|
||||||
msgstr "Postcode"
|
|
||||||
|
|
||||||
#: geo/models.py:345
|
|
||||||
msgid "postal codes"
|
|
||||||
msgstr "Postcodes"
|
|
||||||
|
|
||||||
#: geo/models.py:391
|
|
||||||
msgid "address"
|
|
||||||
msgstr "Adres"
|
|
||||||
|
|
||||||
#: geo/models.py:392
|
|
||||||
msgid "addresses"
|
|
||||||
msgstr "Adressen"
|
|
||||||
|
|
@ -1,133 +0,0 @@
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: 1\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2025-04-28 16:26+0100\n"
|
|
||||||
"PO-Revision-Date: 2025-01-30 03:27+0000\n"
|
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language-Team: BRITISH ENGLISH <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language: pl-PL\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: geo/apps.py:8
|
|
||||||
msgid "geodata"
|
|
||||||
msgstr "Geodane"
|
|
||||||
|
|
||||||
#: geo/conf.py:407
|
|
||||||
msgid "Name"
|
|
||||||
msgstr "Nazwa"
|
|
||||||
|
|
||||||
#: geo/conf.py:408
|
|
||||||
msgid "Abbreviation"
|
|
||||||
msgstr "Skrót"
|
|
||||||
|
|
||||||
#: geo/conf.py:409
|
|
||||||
msgid "Link"
|
|
||||||
msgstr "Link do"
|
|
||||||
|
|
||||||
#: geo/conf.py:413
|
|
||||||
msgid "IATA (Airport) Code"
|
|
||||||
msgstr "Kod IATA (lotniska)"
|
|
||||||
|
|
||||||
#: geo/conf.py:414
|
|
||||||
msgid "ICAO (Airport) Code"
|
|
||||||
msgstr "Kod ICAO (lotniska)"
|
|
||||||
|
|
||||||
#: geo/conf.py:415
|
|
||||||
msgid "FAAC (Airport) Code"
|
|
||||||
msgstr "Kod FAAC (lotnisko)"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:30
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {city_uuid}"
|
|
||||||
msgstr "{name} nie istnieje: {city_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:33
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {postal_code_uuid}"
|
|
||||||
msgstr "{name} nie istnieje: {postal_code_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {uuid}"
|
|
||||||
msgstr "{name} nie istnieje: {uuid}"
|
|
||||||
|
|
||||||
#: geo/models.py:47
|
|
||||||
msgid "UUID"
|
|
||||||
msgstr "Unikalny identyfikator"
|
|
||||||
|
|
||||||
#: geo/models.py:48
|
|
||||||
msgid "active"
|
|
||||||
msgstr "Aktywny"
|
|
||||||
|
|
||||||
#: geo/models.py:54
|
|
||||||
msgid "subclasses_of_place_must_implement_slugify"
|
|
||||||
msgstr "Podklasy `Place` muszą implementować metodę slugify"
|
|
||||||
|
|
||||||
#: geo/models.py:123
|
|
||||||
msgid "continent"
|
|
||||||
msgstr "Kontynent"
|
|
||||||
|
|
||||||
#: geo/models.py:124
|
|
||||||
msgid "continents"
|
|
||||||
msgstr "Kontynenty"
|
|
||||||
|
|
||||||
#: geo/models.py:149 geo/models.py:169
|
|
||||||
msgid "country"
|
|
||||||
msgstr "Kraj"
|
|
||||||
|
|
||||||
#: geo/models.py:150 geo/models.py:170
|
|
||||||
msgid "countries"
|
|
||||||
msgstr "Kraje"
|
|
||||||
|
|
||||||
#: geo/models.py:182
|
|
||||||
msgid "region"
|
|
||||||
msgstr "Region"
|
|
||||||
|
|
||||||
#: geo/models.py:183
|
|
||||||
msgid "regions"
|
|
||||||
msgstr "Regiony"
|
|
||||||
|
|
||||||
#: geo/models.py:205
|
|
||||||
msgid "subregion"
|
|
||||||
msgstr "Podregion"
|
|
||||||
|
|
||||||
#: geo/models.py:206
|
|
||||||
msgid "subregions"
|
|
||||||
msgstr "Podregiony"
|
|
||||||
|
|
||||||
#: geo/models.py:237 geo/models.py:253
|
|
||||||
msgid "city"
|
|
||||||
msgstr "Miasto"
|
|
||||||
|
|
||||||
#: geo/models.py:238 geo/models.py:254
|
|
||||||
msgid "cities"
|
|
||||||
msgstr "Miasta"
|
|
||||||
|
|
||||||
#: geo/models.py:270
|
|
||||||
msgid "district"
|
|
||||||
msgstr "Okręg"
|
|
||||||
|
|
||||||
#: geo/models.py:271
|
|
||||||
msgid "districts"
|
|
||||||
msgstr "Okręgi"
|
|
||||||
|
|
||||||
#: geo/models.py:344
|
|
||||||
msgid "postal code"
|
|
||||||
msgstr "Kod pocztowy"
|
|
||||||
|
|
||||||
#: geo/models.py:345
|
|
||||||
msgid "postal codes"
|
|
||||||
msgstr "Kody pocztowe"
|
|
||||||
|
|
||||||
#: geo/models.py:391
|
|
||||||
msgid "address"
|
|
||||||
msgstr "Adres"
|
|
||||||
|
|
||||||
#: geo/models.py:392
|
|
||||||
msgid "addresses"
|
|
||||||
msgstr "Adresy"
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
# eVibes Translations.
|
|
||||||
# Copyright (C) 2025 Egor "fureunoir" Gorbunov
|
|
||||||
# This file is distributed under the same license as the eVibes package.
|
|
||||||
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: 1\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2025-04-28 16:26+0100\n"
|
|
||||||
"PO-Revision-Date: 2025-01-30 03:27+0000\n"
|
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language-Team: BRITISH ENGLISH <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language: BRITISH ENGLISH\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: geo/apps.py:8
|
|
||||||
msgid "geodata"
|
|
||||||
msgstr "Geodados"
|
|
||||||
|
|
||||||
#: geo/conf.py:407
|
|
||||||
msgid "Name"
|
|
||||||
msgstr "Nome"
|
|
||||||
|
|
||||||
#: geo/conf.py:408
|
|
||||||
msgid "Abbreviation"
|
|
||||||
msgstr "Abreviação"
|
|
||||||
|
|
||||||
#: geo/conf.py:409
|
|
||||||
msgid "Link"
|
|
||||||
msgstr "Link para"
|
|
||||||
|
|
||||||
#: geo/conf.py:413
|
|
||||||
msgid "IATA (Airport) Code"
|
|
||||||
msgstr "Código IATA (aeroporto)"
|
|
||||||
|
|
||||||
#: geo/conf.py:414
|
|
||||||
msgid "ICAO (Airport) Code"
|
|
||||||
msgstr "Código ICAO (aeroporto)"
|
|
||||||
|
|
||||||
#: geo/conf.py:415
|
|
||||||
msgid "FAAC (Airport) Code"
|
|
||||||
msgstr "Código FAAC (Aeroporto)"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:30
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {city_uuid}"
|
|
||||||
msgstr "{name} não existe: {city_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:33
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {postal_code_uuid}"
|
|
||||||
msgstr "{name} não existe: {postal_code_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {uuid}"
|
|
||||||
msgstr "{name} não existe: {uuid}"
|
|
||||||
|
|
||||||
#: geo/models.py:47
|
|
||||||
msgid "UUID"
|
|
||||||
msgstr "ID exclusivo"
|
|
||||||
|
|
||||||
#: geo/models.py:48
|
|
||||||
msgid "active"
|
|
||||||
msgstr "Ativo"
|
|
||||||
|
|
||||||
#: geo/models.py:54
|
|
||||||
msgid "subclasses_of_place_must_implement_slugify"
|
|
||||||
msgstr "As subclasses de `Place` devem implementar o método slugify"
|
|
||||||
|
|
||||||
#: geo/models.py:123
|
|
||||||
msgid "continent"
|
|
||||||
msgstr "Continente"
|
|
||||||
|
|
||||||
#: geo/models.py:124
|
|
||||||
msgid "continents"
|
|
||||||
msgstr "Continentes"
|
|
||||||
|
|
||||||
#: geo/models.py:149 geo/models.py:169
|
|
||||||
msgid "country"
|
|
||||||
msgstr "País"
|
|
||||||
|
|
||||||
#: geo/models.py:150 geo/models.py:170
|
|
||||||
msgid "countries"
|
|
||||||
msgstr "Países"
|
|
||||||
|
|
||||||
#: geo/models.py:182
|
|
||||||
msgid "region"
|
|
||||||
msgstr "Região"
|
|
||||||
|
|
||||||
#: geo/models.py:183
|
|
||||||
msgid "regions"
|
|
||||||
msgstr "Regiões"
|
|
||||||
|
|
||||||
#: geo/models.py:205
|
|
||||||
msgid "subregion"
|
|
||||||
msgstr "Sub-região"
|
|
||||||
|
|
||||||
#: geo/models.py:206
|
|
||||||
msgid "subregions"
|
|
||||||
msgstr "Sub-regiões"
|
|
||||||
|
|
||||||
#: geo/models.py:237 geo/models.py:253
|
|
||||||
msgid "city"
|
|
||||||
msgstr "Cidade"
|
|
||||||
|
|
||||||
#: geo/models.py:238 geo/models.py:254
|
|
||||||
msgid "cities"
|
|
||||||
msgstr "Cidades"
|
|
||||||
|
|
||||||
#: geo/models.py:270
|
|
||||||
msgid "district"
|
|
||||||
msgstr "Distrito"
|
|
||||||
|
|
||||||
#: geo/models.py:271
|
|
||||||
msgid "districts"
|
|
||||||
msgstr "Distritos"
|
|
||||||
|
|
||||||
#: geo/models.py:344
|
|
||||||
msgid "postal code"
|
|
||||||
msgstr "Código postal"
|
|
||||||
|
|
||||||
#: geo/models.py:345
|
|
||||||
msgid "postal codes"
|
|
||||||
msgstr "Códigos postais"
|
|
||||||
|
|
||||||
#: geo/models.py:391
|
|
||||||
msgid "address"
|
|
||||||
msgstr "Endereço"
|
|
||||||
|
|
||||||
#: geo/models.py:392
|
|
||||||
msgid "addresses"
|
|
||||||
msgstr "Endereços"
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
# eVibes Translations.
|
|
||||||
# Copyright (C) 2025 Egor "fureunoir" Gorbunov
|
|
||||||
# This file is distributed under the same license as the eVibes package.
|
|
||||||
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: 1\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2025-04-28 16:26+0100\n"
|
|
||||||
"PO-Revision-Date: 2025-01-30 03:27+0000\n"
|
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language-Team: BRITISH ENGLISH <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language: BRITISH ENGLISH\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: geo/apps.py:8
|
|
||||||
msgid "geodata"
|
|
||||||
msgstr "Geodata"
|
|
||||||
|
|
||||||
#: geo/conf.py:407
|
|
||||||
msgid "Name"
|
|
||||||
msgstr "Nume și prenume"
|
|
||||||
|
|
||||||
#: geo/conf.py:408
|
|
||||||
msgid "Abbreviation"
|
|
||||||
msgstr "Abreviere"
|
|
||||||
|
|
||||||
#: geo/conf.py:409
|
|
||||||
msgid "Link"
|
|
||||||
msgstr "Link către"
|
|
||||||
|
|
||||||
#: geo/conf.py:413
|
|
||||||
msgid "IATA (Airport) Code"
|
|
||||||
msgstr "Cod IATA (Aeroport)"
|
|
||||||
|
|
||||||
#: geo/conf.py:414
|
|
||||||
msgid "ICAO (Airport) Code"
|
|
||||||
msgstr "Cod OACI (Aeroport)"
|
|
||||||
|
|
||||||
#: geo/conf.py:415
|
|
||||||
msgid "FAAC (Airport) Code"
|
|
||||||
msgstr "FAAC (Aeroport) Cod"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:30
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {city_uuid}"
|
|
||||||
msgstr "{name} nu există: {city_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:33
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {postal_code_uuid}"
|
|
||||||
msgstr "{name} nu există: {postal_code_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {uuid}"
|
|
||||||
msgstr "{name} nu există: {uuid}"
|
|
||||||
|
|
||||||
#: geo/models.py:47
|
|
||||||
msgid "UUID"
|
|
||||||
msgstr "ID unic"
|
|
||||||
|
|
||||||
#: geo/models.py:48
|
|
||||||
msgid "active"
|
|
||||||
msgstr "Activ"
|
|
||||||
|
|
||||||
#: geo/models.py:54
|
|
||||||
msgid "subclasses_of_place_must_implement_slugify"
|
|
||||||
msgstr "Subclasele lui `Place` trebuie să implementeze metoda slugify"
|
|
||||||
|
|
||||||
#: geo/models.py:123
|
|
||||||
msgid "continent"
|
|
||||||
msgstr "Continent"
|
|
||||||
|
|
||||||
#: geo/models.py:124
|
|
||||||
msgid "continents"
|
|
||||||
msgstr "Continente"
|
|
||||||
|
|
||||||
#: geo/models.py:149 geo/models.py:169
|
|
||||||
msgid "country"
|
|
||||||
msgstr "Țara"
|
|
||||||
|
|
||||||
#: geo/models.py:150 geo/models.py:170
|
|
||||||
msgid "countries"
|
|
||||||
msgstr "Țări"
|
|
||||||
|
|
||||||
#: geo/models.py:182
|
|
||||||
msgid "region"
|
|
||||||
msgstr "Regiunea"
|
|
||||||
|
|
||||||
#: geo/models.py:183
|
|
||||||
msgid "regions"
|
|
||||||
msgstr "Regiuni"
|
|
||||||
|
|
||||||
#: geo/models.py:205
|
|
||||||
msgid "subregion"
|
|
||||||
msgstr "Subregiune"
|
|
||||||
|
|
||||||
#: geo/models.py:206
|
|
||||||
msgid "subregions"
|
|
||||||
msgstr "Subregiuni"
|
|
||||||
|
|
||||||
#: geo/models.py:237 geo/models.py:253
|
|
||||||
msgid "city"
|
|
||||||
msgstr "Oraș"
|
|
||||||
|
|
||||||
#: geo/models.py:238 geo/models.py:254
|
|
||||||
msgid "cities"
|
|
||||||
msgstr "Orașe"
|
|
||||||
|
|
||||||
#: geo/models.py:270
|
|
||||||
msgid "district"
|
|
||||||
msgstr "Districtul"
|
|
||||||
|
|
||||||
#: geo/models.py:271
|
|
||||||
msgid "districts"
|
|
||||||
msgstr "Districte"
|
|
||||||
|
|
||||||
#: geo/models.py:344
|
|
||||||
msgid "postal code"
|
|
||||||
msgstr "Cod poștal"
|
|
||||||
|
|
||||||
#: geo/models.py:345
|
|
||||||
msgid "postal codes"
|
|
||||||
msgstr "Coduri poștale"
|
|
||||||
|
|
||||||
#: geo/models.py:391
|
|
||||||
msgid "address"
|
|
||||||
msgstr "Adresă"
|
|
||||||
|
|
||||||
#: geo/models.py:392
|
|
||||||
msgid "addresses"
|
|
||||||
msgstr "Adrese"
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
# eVibes Translations.
|
|
||||||
# Copyright (C) 2025 Egor "fureunoir" Gorbunov
|
|
||||||
# This file is distributed under the same license as the eVibes package.
|
|
||||||
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: 1\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2025-04-28 16:26+0100\n"
|
|
||||||
"PO-Revision-Date: 2025-01-30 03:27+0000\n"
|
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language-Team: BRITISH ENGLISH <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language: BRITISH ENGLISH\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: geo/apps.py:8
|
|
||||||
msgid "geodata"
|
|
||||||
msgstr "Геоданные"
|
|
||||||
|
|
||||||
#: geo/conf.py:407
|
|
||||||
msgid "Name"
|
|
||||||
msgstr "Имя"
|
|
||||||
|
|
||||||
#: geo/conf.py:408
|
|
||||||
msgid "Abbreviation"
|
|
||||||
msgstr "Аббревиатура"
|
|
||||||
|
|
||||||
#: geo/conf.py:409
|
|
||||||
msgid "Link"
|
|
||||||
msgstr "Ссылка на"
|
|
||||||
|
|
||||||
#: geo/conf.py:413
|
|
||||||
msgid "IATA (Airport) Code"
|
|
||||||
msgstr "Код IATA (аэропорта)"
|
|
||||||
|
|
||||||
#: geo/conf.py:414
|
|
||||||
msgid "ICAO (Airport) Code"
|
|
||||||
msgstr "Код ИКАО (аэропорта)"
|
|
||||||
|
|
||||||
#: geo/conf.py:415
|
|
||||||
msgid "FAAC (Airport) Code"
|
|
||||||
msgstr "Код FAAC (аэропорт)"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:30
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {city_uuid}"
|
|
||||||
msgstr "{name} не существует: {city_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:33
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {postal_code_uuid}"
|
|
||||||
msgstr "{name} не существует: {postal_code_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {uuid}"
|
|
||||||
msgstr "{name} не существует: {uuid}"
|
|
||||||
|
|
||||||
#: geo/models.py:47
|
|
||||||
msgid "UUID"
|
|
||||||
msgstr "Уникальный идентификатор"
|
|
||||||
|
|
||||||
#: geo/models.py:48
|
|
||||||
msgid "active"
|
|
||||||
msgstr "Активный"
|
|
||||||
|
|
||||||
#: geo/models.py:54
|
|
||||||
msgid "subclasses_of_place_must_implement_slugify"
|
|
||||||
msgstr "Подклассы `Place` должны реализовывать метод slugify"
|
|
||||||
|
|
||||||
#: geo/models.py:123
|
|
||||||
msgid "continent"
|
|
||||||
msgstr "Континент"
|
|
||||||
|
|
||||||
#: geo/models.py:124
|
|
||||||
msgid "continents"
|
|
||||||
msgstr "Континенты"
|
|
||||||
|
|
||||||
#: geo/models.py:149 geo/models.py:169
|
|
||||||
msgid "country"
|
|
||||||
msgstr "Страна"
|
|
||||||
|
|
||||||
#: geo/models.py:150 geo/models.py:170
|
|
||||||
msgid "countries"
|
|
||||||
msgstr "Страны"
|
|
||||||
|
|
||||||
#: geo/models.py:182
|
|
||||||
msgid "region"
|
|
||||||
msgstr "Регион"
|
|
||||||
|
|
||||||
#: geo/models.py:183
|
|
||||||
msgid "regions"
|
|
||||||
msgstr "Регионы"
|
|
||||||
|
|
||||||
#: geo/models.py:205
|
|
||||||
msgid "subregion"
|
|
||||||
msgstr "Субрегион"
|
|
||||||
|
|
||||||
#: geo/models.py:206
|
|
||||||
msgid "subregions"
|
|
||||||
msgstr "Субрегионы"
|
|
||||||
|
|
||||||
#: geo/models.py:237 geo/models.py:253
|
|
||||||
msgid "city"
|
|
||||||
msgstr "Город"
|
|
||||||
|
|
||||||
#: geo/models.py:238 geo/models.py:254
|
|
||||||
msgid "cities"
|
|
||||||
msgstr "Города"
|
|
||||||
|
|
||||||
#: geo/models.py:270
|
|
||||||
msgid "district"
|
|
||||||
msgstr "Округ"
|
|
||||||
|
|
||||||
#: geo/models.py:271
|
|
||||||
msgid "districts"
|
|
||||||
msgstr "Районы"
|
|
||||||
|
|
||||||
#: geo/models.py:344
|
|
||||||
msgid "postal code"
|
|
||||||
msgstr "Почтовый индекс"
|
|
||||||
|
|
||||||
#: geo/models.py:345
|
|
||||||
msgid "postal codes"
|
|
||||||
msgstr "Почтовые индексы"
|
|
||||||
|
|
||||||
#: geo/models.py:391
|
|
||||||
msgid "address"
|
|
||||||
msgstr "Адрес"
|
|
||||||
|
|
||||||
#: geo/models.py:392
|
|
||||||
msgid "addresses"
|
|
||||||
msgstr "Адреса"
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
# eVibes Translations.
|
|
||||||
# Copyright (C) 2025 Egor "fureunoir" Gorbunov
|
|
||||||
# This file is distributed under the same license as the eVibes package.
|
|
||||||
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: 1\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2025-04-28 16:26+0100\n"
|
|
||||||
"PO-Revision-Date: 2025-01-30 03:27+0000\n"
|
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language-Team: CHINESE SIMPLIFIED <CONTACT@FUREUNOIR.COM>\n"
|
|
||||||
"Language: CHINESE SIMPLIFIED\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: geo/apps.py:8
|
|
||||||
msgid "geodata"
|
|
||||||
msgstr "地理数据"
|
|
||||||
|
|
||||||
#: geo/conf.py:407
|
|
||||||
msgid "Name"
|
|
||||||
msgstr "名称"
|
|
||||||
|
|
||||||
#: geo/conf.py:408
|
|
||||||
msgid "Abbreviation"
|
|
||||||
msgstr "缩写"
|
|
||||||
|
|
||||||
#: geo/conf.py:409
|
|
||||||
msgid "Link"
|
|
||||||
msgstr "链接到"
|
|
||||||
|
|
||||||
#: geo/conf.py:413
|
|
||||||
msgid "IATA (Airport) Code"
|
|
||||||
msgstr "空运协会(机场)代码"
|
|
||||||
|
|
||||||
#: geo/conf.py:414
|
|
||||||
msgid "ICAO (Airport) Code"
|
|
||||||
msgstr "国际民航组织(机场)代码"
|
|
||||||
|
|
||||||
#: geo/conf.py:415
|
|
||||||
msgid "FAAC (Airport) Code"
|
|
||||||
msgstr "FAAC (机场)代码"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:30
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {city_uuid}"
|
|
||||||
msgstr "{name} 不存在:{city_uuid}"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:33
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {postal_code_uuid}"
|
|
||||||
msgstr "{name} 不存在:{postal_code_uuid}不存在"
|
|
||||||
|
|
||||||
#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{name} does not exist: {uuid}"
|
|
||||||
msgstr "{name} 不存在:{uuid}"
|
|
||||||
|
|
||||||
#: geo/models.py:47
|
|
||||||
msgid "UUID"
|
|
||||||
msgstr "唯一 ID"
|
|
||||||
|
|
||||||
#: geo/models.py:48
|
|
||||||
msgid "active"
|
|
||||||
msgstr "活跃"
|
|
||||||
|
|
||||||
#: geo/models.py:54
|
|
||||||
msgid "subclasses_of_place_must_implement_slugify"
|
|
||||||
msgstr "Place \"的子类必须实现 slugify 方法"
|
|
||||||
|
|
||||||
#: geo/models.py:123
|
|
||||||
msgid "continent"
|
|
||||||
msgstr "大陆"
|
|
||||||
|
|
||||||
#: geo/models.py:124
|
|
||||||
msgid "continents"
|
|
||||||
msgstr "各大洲"
|
|
||||||
|
|
||||||
#: geo/models.py:149 geo/models.py:169
|
|
||||||
msgid "country"
|
|
||||||
msgstr "国家"
|
|
||||||
|
|
||||||
#: geo/models.py:150 geo/models.py:170
|
|
||||||
msgid "countries"
|
|
||||||
msgstr "国家"
|
|
||||||
|
|
||||||
#: geo/models.py:182
|
|
||||||
msgid "region"
|
|
||||||
msgstr "地区"
|
|
||||||
|
|
||||||
#: geo/models.py:183
|
|
||||||
msgid "regions"
|
|
||||||
msgstr "地区"
|
|
||||||
|
|
||||||
#: geo/models.py:205
|
|
||||||
msgid "subregion"
|
|
||||||
msgstr "次区域"
|
|
||||||
|
|
||||||
#: geo/models.py:206
|
|
||||||
msgid "subregions"
|
|
||||||
msgstr "次区域"
|
|
||||||
|
|
||||||
#: geo/models.py:237 geo/models.py:253
|
|
||||||
msgid "city"
|
|
||||||
msgstr "城市"
|
|
||||||
|
|
||||||
#: geo/models.py:238 geo/models.py:254
|
|
||||||
msgid "cities"
|
|
||||||
msgstr "城市"
|
|
||||||
|
|
||||||
#: geo/models.py:270
|
|
||||||
msgid "district"
|
|
||||||
msgstr "地区"
|
|
||||||
|
|
||||||
#: geo/models.py:271
|
|
||||||
msgid "districts"
|
|
||||||
msgstr "地区"
|
|
||||||
|
|
||||||
#: geo/models.py:344
|
|
||||||
msgid "postal code"
|
|
||||||
msgstr "邮政编码"
|
|
||||||
|
|
||||||
#: geo/models.py:345
|
|
||||||
msgid "postal codes"
|
|
||||||
msgstr "邮政编码"
|
|
||||||
|
|
||||||
#: geo/models.py:391
|
|
||||||
msgid "address"
|
|
||||||
msgstr "地址"
|
|
||||||
|
|
||||||
#: geo/models.py:392
|
|
||||||
msgid "addresses"
|
|
||||||
msgstr "地址"
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
import requests
|
|
||||||
from constance import config
|
|
||||||
from django.contrib.gis.geos import Point
|
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
|
|
||||||
class AddressManager(models.Manager):
|
|
||||||
def create(self, raw_data: str, **kwargs):
|
|
||||||
"""
|
|
||||||
Create an Address instance by geocoding the provided raw address string.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
raw_data (str): The raw address input from the user (e.g., '36 Mornington Rd Loughton England').
|
|
||||||
**kwargs: Additional fields to pass to the Address model (e.g., user).
|
|
||||||
"""
|
|
||||||
if not raw_data:
|
|
||||||
raise ValueError("'raw_data' (address string) must be provided.")
|
|
||||||
|
|
||||||
# Query Nominatim
|
|
||||||
params = {
|
|
||||||
'format': 'json',
|
|
||||||
'addressdetails': 1,
|
|
||||||
'q': raw_data,
|
|
||||||
}
|
|
||||||
resp = requests.get(config.NOMINATIM_URL, params=params)
|
|
||||||
resp.raise_for_status()
|
|
||||||
results = resp.json()
|
|
||||||
if not results:
|
|
||||||
raise ValueError(f"No geocoding result for address: {raw_data}")
|
|
||||||
data = results[0]
|
|
||||||
|
|
||||||
# Parse address components
|
|
||||||
addr = data.get('address', {})
|
|
||||||
street = addr.get('road') or addr.get('pedestrian') or ''
|
|
||||||
district = addr.get('city_district') or addr.get('suburb') or ''
|
|
||||||
city = addr.get('city') or addr.get('town') or addr.get('village') or ''
|
|
||||||
region = addr.get('state') or addr.get('region') or ''
|
|
||||||
postal_code = addr.get('postcode') or ''
|
|
||||||
country = addr.get('country') or ''
|
|
||||||
|
|
||||||
# Parse location
|
|
||||||
try:
|
|
||||||
lat = float(data.get('lat'))
|
|
||||||
lon = float(data.get('lon'))
|
|
||||||
location = Point(lon, lat, srid=4326)
|
|
||||||
except (TypeError, ValueError):
|
|
||||||
location = None
|
|
||||||
|
|
||||||
# Create the model instance, storing both the input string and full API response
|
|
||||||
return super().create(
|
|
||||||
raw_data=raw_data,
|
|
||||||
street=street,
|
|
||||||
district=district,
|
|
||||||
city=city,
|
|
||||||
region=region,
|
|
||||||
postal_code=postal_code,
|
|
||||||
country=country,
|
|
||||||
location=location,
|
|
||||||
api_response=data,
|
|
||||||
**kwargs
|
|
||||||
)
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
# Generated by Django 5.2 on 2025-05-19 11:40
|
|
||||||
|
|
||||||
import django.contrib.gis.db.models.fields
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies = [
|
|
||||||
('geo', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='address',
|
|
||||||
name='api_response',
|
|
||||||
field=models.JSONField(blank=True, help_text='stored JSON response from the geocoding service', null=True),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='address',
|
|
||||||
name='location',
|
|
||||||
field=django.contrib.gis.db.models.fields.PointField(blank=True, geography=True,
|
|
||||||
help_text='geolocation point: (longitude, latitude)',
|
|
||||||
null=True, srid=4326),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='address',
|
|
||||||
name='raw_data',
|
|
||||||
field=models.JSONField(blank=True, help_text='full JSON response from geocoder for this address',
|
|
||||||
null=True),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
from django.contrib.gis.db import models as gis_models
|
|
||||||
from django.db import models
|
|
||||||
from django.db.models import Index
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
|
|
||||||
from core.abstract import NiceModel
|
|
||||||
from geo.managers import AddressManager
|
|
||||||
|
|
||||||
|
|
||||||
class Address(NiceModel):
|
|
||||||
street = models.CharField(_("street"), max_length=255, null=True) # noqa: DJ001
|
|
||||||
district = models.CharField(_("district"), max_length=255, null=True) # noqa: DJ001
|
|
||||||
city = models.CharField(_("city"), max_length=100, null=True) # noqa: DJ001
|
|
||||||
region = models.CharField(_("region"), max_length=100, null=True) # noqa: DJ001
|
|
||||||
postal_code = models.CharField(_("postal code"), max_length=20, null=True) # noqa: DJ001
|
|
||||||
country = models.CharField(_("country"), max_length=40, null=True) # noqa: DJ001
|
|
||||||
|
|
||||||
location = gis_models.PointField(
|
|
||||||
geography=True,
|
|
||||||
srid=4326,
|
|
||||||
null=True,
|
|
||||||
blank=True,
|
|
||||||
help_text=_("geolocation point: (longitude, latitude)")
|
|
||||||
)
|
|
||||||
|
|
||||||
raw_data = models.JSONField(
|
|
||||||
blank=True,
|
|
||||||
null=True,
|
|
||||||
help_text=_("full JSON response from geocoder for this address")
|
|
||||||
)
|
|
||||||
|
|
||||||
api_response = models.JSONField(
|
|
||||||
blank=True,
|
|
||||||
null=True,
|
|
||||||
help_text=_("stored JSON response from the geocoding service")
|
|
||||||
)
|
|
||||||
|
|
||||||
user = models.ForeignKey(
|
|
||||||
to="vibes_auth.User",
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
blank=True,
|
|
||||||
null=True
|
|
||||||
)
|
|
||||||
|
|
||||||
objects = AddressManager()
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
verbose_name = _("address")
|
|
||||||
verbose_name_plural = _("addresses")
|
|
||||||
indexes = [
|
|
||||||
Index(fields=["location"]),
|
|
||||||
]
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
base = f"{self.street}, {self.city}, {self.country}"
|
|
||||||
return f"{base} for {self.user.email}" if self.user else base
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
from rest_framework import serializers
|
|
||||||
|
|
||||||
from geo.models import Address
|
|
||||||
|
|
||||||
|
|
||||||
class AddressAutocompleteInputSerializer(serializers.Serializer):
|
|
||||||
q = serializers.CharField(
|
|
||||||
required=True
|
|
||||||
)
|
|
||||||
limit = serializers.IntegerField(
|
|
||||||
required=False,
|
|
||||||
min_value=1,
|
|
||||||
max_value=10,
|
|
||||||
default=5
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class AddressSuggestionSerializer(serializers.Serializer):
|
|
||||||
display_name = serializers.CharField()
|
|
||||||
lat = serializers.FloatField()
|
|
||||||
lon = serializers.FloatField()
|
|
||||||
address = serializers.DictField(child=serializers.CharField())
|
|
||||||
|
|
||||||
|
|
||||||
class AddressSerializer(serializers.ModelSerializer):
|
|
||||||
latitude = serializers.FloatField(source="location.y", read_only=True)
|
|
||||||
longitude = serializers.FloatField(source="location.x", read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Address
|
|
||||||
fields = [
|
|
||||||
"uuid",
|
|
||||||
"street",
|
|
||||||
"district",
|
|
||||||
"city",
|
|
||||||
"region",
|
|
||||||
"postal_code",
|
|
||||||
"country",
|
|
||||||
"latitude",
|
|
||||||
"longitude",
|
|
||||||
"raw_data",
|
|
||||||
"api_response",
|
|
||||||
"user",
|
|
||||||
]
|
|
||||||
read_only_fields = [
|
|
||||||
"latitude",
|
|
||||||
"longitude",
|
|
||||||
"raw_data",
|
|
||||||
"api_response",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class AddressCreateSerializer(serializers.ModelSerializer):
|
|
||||||
raw_data = serializers.CharField(
|
|
||||||
write_only=True,
|
|
||||||
max_length=512,
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Address
|
|
||||||
fields = ["raw_data", "user"]
|
|
||||||
|
|
||||||
def create(self, validated_data):
|
|
||||||
raw = validated_data.pop("raw_data")
|
|
||||||
return Address.objects.create(raw_data=raw, **validated_data)
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
from django.test import TestCase # noqa: F401
|
|
||||||
|
|
||||||
# Create your tests here.
|
|
||||||
11
geo/urls.py
|
|
@ -1,11 +0,0 @@
|
||||||
from django.urls import include, path
|
|
||||||
from rest_framework.routers import DefaultRouter
|
|
||||||
|
|
||||||
from geo.viewsets import AddressViewSet
|
|
||||||
|
|
||||||
geo_router = DefaultRouter()
|
|
||||||
geo_router.register(r"addresses", AddressViewSet, basename="addresses")
|
|
||||||
|
|
||||||
urlpatterns = [
|
|
||||||
path(r"", include(geo_router.urls)),
|
|
||||||
]
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
from django.contrib.gis.db.models import PointField
|
|
||||||
from django.contrib.gis.geos import Point
|
|
||||||
from graphene.types.scalars import Scalar
|
|
||||||
from graphene_django.converter import convert_django_field
|
|
||||||
from graphql.language import ast
|
|
||||||
|
|
||||||
|
|
||||||
class PointScalar(Scalar):
|
|
||||||
"""Custom scalar for GeoDjango PointField"""
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def serialize(point):
|
|
||||||
if not isinstance(point, Point):
|
|
||||||
raise Exception("Expected a Point instance")
|
|
||||||
return {"x": point.x, "y": point.y}
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def parse_literal(node):
|
|
||||||
if isinstance(node, ast.ObjectValue):
|
|
||||||
return Point(x=node.value["x"], y=node.value["y"])
|
|
||||||
return None
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def parse_value(value):
|
|
||||||
if isinstance(value, dict):
|
|
||||||
return Point(x=value["x"], y=value["y"])
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
@convert_django_field.register(PointField)
|
|
||||||
def convert_point_field_to_custom_type(field, registry=None):
|
|
||||||
return PointScalar(description=field.help_text, required=not field.null)
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
from drf_spectacular.utils import extend_schema_view
|
|
||||||
from rest_framework import status, viewsets
|
|
||||||
from rest_framework.decorators import action
|
|
||||||
from rest_framework.permissions import IsAdminUser
|
|
||||||
from rest_framework.response import Response
|
|
||||||
|
|
||||||
from core.permissions import IsOwner
|
|
||||||
from geo.docs.drf.viewsets import ADDRESS_SCHEMA
|
|
||||||
from geo.models import Address
|
|
||||||
from geo.serializers import AddressAutocompleteInputSerializer, AddressCreateSerializer, AddressSerializer
|
|
||||||
from geo.utils.nominatim import fetch_address_suggestions
|
|
||||||
|
|
||||||
|
|
||||||
@extend_schema_view(**ADDRESS_SCHEMA)
|
|
||||||
class AddressViewSet(viewsets.ModelViewSet):
|
|
||||||
queryset = Address.objects.all()
|
|
||||||
serializer_class = AddressSerializer
|
|
||||||
permission_classes = [IsOwner, IsAdminUser]
|
|
||||||
|
|
||||||
def get_serializer_class(self):
|
|
||||||
if self.action == 'create':
|
|
||||||
return AddressCreateSerializer
|
|
||||||
if self.action == 'autocomplete':
|
|
||||||
return AddressAutocompleteInputSerializer
|
|
||||||
return AddressSerializer
|
|
||||||
|
|
||||||
@action(detail=False, methods=["get"], url_path="autocomplete")
|
|
||||||
def autocomplete(self, request):
|
|
||||||
serializer = AddressAutocompleteInputSerializer(data=request.query_params)
|
|
||||||
serializer.is_valid(raise_exception=True)
|
|
||||||
|
|
||||||
q = serializer.validated_data["q"]
|
|
||||||
limit = serializer.validated_data["limit"]
|
|
||||||
|
|
||||||
try:
|
|
||||||
suggestions = fetch_address_suggestions(query=q, limit=limit)
|
|
||||||
except Exception as e:
|
|
||||||
return Response(
|
|
||||||
{"detail": _(f"Geocoding error: {e}")},
|
|
||||||
status=status.HTTP_502_BAD_GATEWAY,
|
|
||||||
)
|
|
||||||
|
|
||||||
return Response(suggestions, status=status.HTTP_200_OK)
|
|
||||||
|
|
@ -9,7 +9,7 @@ from core.abstract import NiceModel
|
||||||
class Balance(NiceModel):
|
class Balance(NiceModel):
|
||||||
amount = FloatField(null=False, blank=False, default=0)
|
amount = FloatField(null=False, blank=False, default=0)
|
||||||
user = OneToOneField(
|
user = OneToOneField(
|
||||||
to="vibes_auth.User", on_delete=CASCADE, blank=False, null=False, related_name="payments_balance"
|
to="vibes_auth.User", on_delete=CASCADE, blank=True, null=True, related_name="payments_balance"
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
|
||||||