diff --git a/AUTHORS b/AUTHORS index d34e882494..fb299a9e3b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -72,6 +72,7 @@ answer newbie questions, and generally made Django that much better: junzhang.jn@gmail.com Russell Keith-Magee Garth Kidd + kilian Sune Kirkeby Cameron Knight (ckknight) Bruce Kroeze diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py index ec201893f8..e42019ece7 100644 --- a/django/conf/global_settings.py +++ b/django/conf/global_settings.py @@ -36,6 +36,7 @@ LANGUAGE_CODE = 'en-us' # Languages we provide translations for, out of the box. The language name # should be the utf-8 encoded local name for the language. LANGUAGES = ( + ('ar', gettext_noop('Arabic')), ('bn', gettext_noop('Bengali')), ('cs', gettext_noop('Czech')), ('cy', gettext_noop('Welsh')), @@ -67,7 +68,7 @@ LANGUAGES = ( ) # Languages using BiDi (right-to-left) layout -LANGUAGES_BIDI = ("he",) +LANGUAGES_BIDI = ("he", "ar") # If you set this to False, Django will make some optimizations so as not # to load the internationalization machinery. diff --git a/django/conf/locale/ar/LC_MESSAGES/django.mo b/django/conf/locale/ar/LC_MESSAGES/django.mo new file mode 100644 index 0000000000..323e53321d Binary files /dev/null and b/django/conf/locale/ar/LC_MESSAGES/django.mo differ diff --git a/django/conf/locale/ar/LC_MESSAGES/django.po b/django/conf/locale/ar/LC_MESSAGES/django.po new file mode 100644 index 0000000000..203d50d7de --- /dev/null +++ b/django/conf/locale/ar/LC_MESSAGES/django.po @@ -0,0 +1,1989 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the django package. +# Ahmad Alhashemi , 2006. +# +msgid "" +msgstr "" +"Project-Id-Version: Django SVN\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2006-07-03 19:22+0300\n" +"PO-Revision-Date: 2006-07-06 23:46+0300\n" +"Last-Translator: Ahmad Alhashemi \n" +"Language-Team: Ahmad Alhashemi \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n == 1? 0 : (n == 2? 1 : (n <= 10? 2 : 3)));\n" +"X-Poedit-Language: Arabic\n" +"X-Poedit-Country: KUWAIT\n" +"X-Poedit-SourceCharset: utf-8\n" + +#: .\conf\global_settings.py:37 +msgid "Bengali" +msgstr "بنغالي" + +#: .\conf\global_settings.py:38 +msgid "Czech" +msgstr "تشيكي" + +#: .\conf\global_settings.py:39 +msgid "Welsh" +msgstr "ويلزي" + +#: .\conf\global_settings.py:40 +msgid "Danish" +msgstr "دنماركي" + +#: .\conf\global_settings.py:41 +msgid "German" +msgstr "ألماني" + +#: .\conf\global_settings.py:42 +msgid "Greek" +msgstr "اغريقي" + +#: .\conf\global_settings.py:43 +msgid "English" +msgstr "انجليزي" + +#: .\conf\global_settings.py:44 +msgid "Spanish" +msgstr "اسباني" + +#: .\conf\global_settings.py:45 +msgid "Argentinean Spanish" +msgstr "اسباني أرجنتيني" + +#: .\conf\global_settings.py:46 +msgid "French" +msgstr "فرنسي" + +#: .\conf\global_settings.py:47 +msgid "Galician" +msgstr "جاليسي" + +#: .\conf\global_settings.py:48 +msgid "Hungarian" +msgstr "هنغاري" + +#: .\conf\global_settings.py:49 +msgid "Hebrew" +msgstr "عبري" + +#: .\conf\global_settings.py:50 +msgid "Icelandic" +msgstr "آيسلندي" + +#: .\conf\global_settings.py:51 +msgid "Italian" +msgstr "ايطالي" + +#: .\conf\global_settings.py:52 +msgid "Japanese" +msgstr "ياباني" + +#: .\conf\global_settings.py:53 +msgid "Dutch" +msgstr "هولندي" + +#: .\conf\global_settings.py:54 +msgid "Norwegian" +msgstr "نرويجي" + +#: .\conf\global_settings.py:55 +msgid "Brazilian" +msgstr "برازيلي" + +#: .\conf\global_settings.py:56 +msgid "Romanian" +msgstr "روماني" + +#: .\conf\global_settings.py:57 +msgid "Russian" +msgstr "روسي" + +#: .\conf\global_settings.py:58 +msgid "Slovak" +msgstr "سلوفاك" + +#: .\conf\global_settings.py:59 +msgid "Slovenian" +msgstr "سلوفاتي" + +#: .\conf\global_settings.py:60 +msgid "Serbian" +msgstr "صربي" + +#: .\conf\global_settings.py:61 +msgid "Swedish" +msgstr "سويدي" + +#: .\conf\global_settings.py:62 +msgid "Ukrainian" +msgstr "أكراني" + +#: .\conf\global_settings.py:63 +msgid "Simplified Chinese" +msgstr "صيني مبسط" + +#: .\conf\global_settings.py:64 +msgid "Traditional Chinese" +msgstr "صيني تقليدي" + +#: .\contrib\admin\filterspecs.py:40 +#, python-format +msgid "" +"

By %s:

\n" +"
    \n" +msgstr "" +"

    بواسطة %s:

    \n" +"
      \n" + +#: .\contrib\admin\filterspecs.py:70 +#: .\contrib\admin\filterspecs.py:88 +#: .\contrib\admin\filterspecs.py:143 +#: .\contrib\admin\filterspecs.py:169 +msgid "All" +msgstr "كافة" + +#: .\contrib\admin\filterspecs.py:109 +msgid "Any date" +msgstr "أي تاريخ" + +#: .\contrib\admin\filterspecs.py:110 +msgid "Today" +msgstr "اليوم" + +#: .\contrib\admin\filterspecs.py:113 +msgid "Past 7 days" +msgstr "الأيام 7 الماضية" + +#: .\contrib\admin\filterspecs.py:115 +msgid "This month" +msgstr "هذا الشهر" + +#: .\contrib\admin\filterspecs.py:117 +msgid "This year" +msgstr "هذه السنة" + +#: .\contrib\admin\filterspecs.py:143 +msgid "Yes" +msgstr "نعم" + +#: .\contrib\admin\filterspecs.py:143 +msgid "No" +msgstr "لا" + +#: .\contrib\admin\filterspecs.py:150 +msgid "Unknown" +msgstr "غير معروف" + +#: .\contrib\admin\models.py:16 +msgid "action time" +msgstr "وقت العملية" + +#: .\contrib\admin\models.py:19 +msgid "object id" +msgstr "معرف العنصر" + +#: .\contrib\admin\models.py:20 +msgid "object repr" +msgstr "ممثل العنصر" + +#: .\contrib\admin\models.py:21 +msgid "action flag" +msgstr "علامة العملية" + +#: .\contrib\admin\models.py:22 +msgid "change message" +msgstr "تغيير الرسالة" + +#: .\contrib\admin\models.py:25 +msgid "log entry" +msgstr "مدخل السجل" + +#: .\contrib\admin\models.py:26 +msgid "log entries" +msgstr "مدخلات السجل" + +#: .\contrib\admin\templates\admin\404.html.py:4 +#: .\contrib\admin\templates\admin\404.html.py:8 +msgid "Page not found" +msgstr "تعذر العثور على الصفحة" + +#: .\contrib\admin\templates\admin\404.html.py:10 +msgid "We're sorry, but the requested page could not be found." +msgstr "نحن آسفون، لكننا لم نعثر على الصفحة المطلوبة." + +#: .\contrib\admin\templates\admin\500.html.py:4 +#: .\contrib\admin\templates\admin\base.html.py:29 +#: .\contrib\admin\templates\admin\change_form.html.py:13 +#: .\contrib\admin\templates\admin\change_list.html.py:6 +#: .\contrib\admin\templates\admin\delete_confirmation.html.py:6 +#: .\contrib\admin\templates\admin\invalid_setup.html.py:4 +#: .\contrib\admin\templates\admin\object_history.html.py:5 +#: .\contrib\admin\templates\admin_doc\bookmarklets.html.py:3 +#: .\contrib\admin\templates\registration\logged_out.html.py:4 +#: .\contrib\admin\templates\registration\password_change_done.html.py:4 +#: .\contrib\admin\templates\registration\password_change_form.html.py:4 +#: .\contrib\admin\templates\registration\password_reset_done.html.py:4 +#: .\contrib\admin\templates\registration\password_reset_form.html.py:4 +msgid "Home" +msgstr "الرئيسية" + +#: .\contrib\admin\templates\admin\500.html.py:4 +msgid "Server error" +msgstr "خطأ في المزود" + +#: .\contrib\admin\templates\admin\500.html.py:6 +msgid "Server error (500)" +msgstr "خطأ في المزود (500)" + +#: .\contrib\admin\templates\admin\500.html.py:9 +msgid "Server Error (500)" +msgstr "خطأ في المزود (500)" + +#: .\contrib\admin\templates\admin\500.html.py:10 +msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience." +msgstr "حدث خطأ، وقم تم الابلاغ عنه إلى مدراء الموقع عبر البريد الإلكترونيوسيتم حل المشكلة قريبا إن شاء الله، شكرا لك على صبرك." + +#: .\contrib\admin\templates\admin\base.html.py:24 +msgid "Welcome," +msgstr "أهلا، " + +#: .\contrib\admin\templates\admin\base.html.py:24 +#: .\contrib\admin\templates\admin\change_form.html.py:10 +#: .\contrib\admin\templates\admin\change_list.html.py:5 +#: .\contrib\admin\templates\admin\delete_confirmation.html.py:3 +#: .\contrib\admin\templates\admin\object_history.html.py:3 +#: .\contrib\admin\templates\admin_doc\bookmarklets.html.py:3 +#: .\contrib\admin\templates\registration\password_change_done.html.py:3 +#: .\contrib\admin\templates\registration\password_change_form.html.py:3 +msgid "Documentation" +msgstr "التعليمات" + +#: .\contrib\admin\templates\admin\base.html.py:24 +#: .\contrib\admin\templates\admin\change_form.html.py:10 +#: .\contrib\admin\templates\admin\change_list.html.py:5 +#: .\contrib\admin\templates\admin\delete_confirmation.html.py:3 +#: .\contrib\admin\templates\admin\object_history.html.py:3 +#: .\contrib\admin\templates\admin_doc\bookmarklets.html.py:4 +#: .\contrib\admin\templates\admin_doc\index.html.py:4 +#: .\contrib\admin\templates\admin_doc\missing_docutils.html.py:4 +#: .\contrib\admin\templates\admin_doc\model_detail.html.py:3 +#: .\contrib\admin\templates\admin_doc\model_index.html.py:5 +#: .\contrib\admin\templates\admin_doc\template_detail.html.py:4 +#: .\contrib\admin\templates\admin_doc\template_filter_index.html.py:5 +#: .\contrib\admin\templates\admin_doc\template_tag_index.html.py:5 +#: .\contrib\admin\templates\admin_doc\view_detail.html.py:4 +#: .\contrib\admin\templates\admin_doc\view_index.html.py:5 +#: .\contrib\admin\templates\registration\password_change_done.html.py:3 +#: .\contrib\admin\templates\registration\password_change_form.html.py:3 +msgid "Change password" +msgstr "تغيير كلمة المرور" + +#: .\contrib\admin\templates\admin\base.html.py:24 +#: .\contrib\admin\templates\admin\change_form.html.py:10 +#: .\contrib\admin\templates\admin\change_list.html.py:5 +#: .\contrib\admin\templates\admin\delete_confirmation.html.py:3 +#: .\contrib\admin\templates\admin\object_history.html.py:3 +#: .\contrib\admin\templates\admin_doc\bookmarklets.html.py:4 +#: .\contrib\admin\templates\admin_doc\index.html.py:4 +#: .\contrib\admin\templates\admin_doc\missing_docutils.html.py:4 +#: .\contrib\admin\templates\admin_doc\model_detail.html.py:3 +#: .\contrib\admin\templates\admin_doc\model_index.html.py:5 +#: .\contrib\admin\templates\admin_doc\template_detail.html.py:4 +#: .\contrib\admin\templates\admin_doc\template_filter_index.html.py:5 +#: .\contrib\admin\templates\admin_doc\template_tag_index.html.py:5 +#: .\contrib\admin\templates\admin_doc\view_detail.html.py:4 +#: .\contrib\admin\templates\admin_doc\view_index.html.py:5 +#: .\contrib\admin\templates\registration\password_change_done.html.py:3 +#: .\contrib\admin\templates\registration\password_change_form.html.py:3 +#: .\contrib\comments\templates\comments\form.html.py:8 +msgid "Log out" +msgstr "خروج" + +#: .\contrib\admin\templates\admin\base_site.html.py:4 +msgid "Django site admin" +msgstr "إدارة موقع جاننغو" + +#: .\contrib\admin\templates\admin\base_site.html.py:7 +msgid "Django administration" +msgstr "إدارة جانغو" + +#: .\contrib\admin\templates\admin\change_form.html.py:15 +#: .\contrib\admin\templates\admin\index.html.py:28 +msgid "Add" +msgstr "إضافة" + +#: .\contrib\admin\templates\admin\change_form.html.py:20 +#: .\contrib\admin\templates\admin\object_history.html.py:5 +msgid "History" +msgstr "تاريخ" + +#: .\contrib\admin\templates\admin\change_form.html.py:21 +msgid "View on site" +msgstr "عرض على الموقع" + +#: .\contrib\admin\templates\admin\change_form.html.py:30 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "الرجاء اصلاح الخطأ التالي." +msgstr[1] "الرجاء اصلاح الخطئين التاليين." +msgstr[2] "الرجاء اصلاح الأخطاء التالية." +msgstr[3] "الرجاء اصلاح الأخطاء التالية." + +#: .\contrib\admin\templates\admin\change_form.html.py:48 +msgid "Ordering" +msgstr "الترتيب" + +#: .\contrib\admin\templates\admin\change_form.html.py:51 +msgid "Order:" +msgstr "الترتيب" + +#: .\contrib\admin\templates\admin\change_list.html.py:11 +#, python-format +msgid "Add %(name)s" +msgstr "اضافة %(name)s" + +#: .\contrib\admin\templates\admin\delete_confirmation.html.py:9 +#: .\contrib\admin\templates\admin\submit_line.html.py:3 +msgid "Delete" +msgstr "حذف" + +#: .\contrib\admin\templates\admin\delete_confirmation.html.py:14 +#, python-format +msgid "Deleting the %(object_name)s '%(object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgstr "حذف %(object_name)s '%(object)s' سيؤدي إلى حذف العناصر المتعلقة به، لكن هذا الحساب لا يملك الصلاحية لحذف أنواع العناصر التالية:" + +#: .\contrib\admin\templates\admin\delete_confirmation.html.py:21 +#, python-format +msgid "Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of the following related items will be deleted:" +msgstr "هل أنت متأكد من أنك تريد حذف %(object_name)s \"%(object)s\"? كافة العناصر التالية المتعلقة به سيتم حذفها:" + +#: .\contrib\admin\templates\admin\delete_confirmation.html.py:26 +msgid "Yes, I'm sure" +msgstr "نعم، أنا متأكد" + +#: .\contrib\admin\templates\admin\filter.html.py:2 +#, python-format +msgid " By %(title)s " +msgstr " بواسطة %(title)s " + +#: .\contrib\admin\templates\admin\filters.html.py:4 +msgid "Filter" +msgstr "مرشح" + +#: .\contrib\admin\templates\admin\index.html.py:17 +#, python-format +msgid "Models available in the %(name)s application." +msgstr "النماذج المتوفرة في برنامج %(name)s." + +#: .\contrib\admin\templates\admin\index.html.py:34 +msgid "Change" +msgstr "تغيير" + +#: .\contrib\admin\templates\admin\index.html.py:44 +msgid "You don't have permission to edit anything." +msgstr "ليست لديك الصلاحية لتعديل أي شيء." + +#: .\contrib\admin\templates\admin\index.html.py:52 +msgid "Recent Actions" +msgstr "العمليات الأخيرة" + +#: .\contrib\admin\templates\admin\index.html.py:53 +msgid "My Actions" +msgstr "عملياتي" + +#: .\contrib\admin\templates\admin\index.html.py:57 +msgid "None available" +msgstr "لا يوجد" + +#: .\contrib\admin\templates\admin\invalid_setup.html.py:8 +msgid "Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user." +msgstr "هنالك أمر خاطئ في تركيب قاعدة بياناتك، تأكد من أنه تم انشاء جداول قاعدة البيانات الملائمة، وتأكد من أن قاعدة البيانات قابلة للقراءة من قبل المستخدم الملائم." + +#: .\contrib\admin\templates\admin\login.html.py:17 +#: .\contrib\comments\templates\comments\form.html.py:6 +#: .\contrib\comments\templates\comments\form.html.py:8 +msgid "Username:" +msgstr "اسم المستخدم:" + +#: .\contrib\admin\templates\admin\login.html.py:20 +#: .\contrib\comments\templates\comments\form.html.py:6 +msgid "Password:" +msgstr "كلمة المرور:" + +#: .\contrib\admin\templates\admin\login.html.py:22 +msgid "Have you forgotten your password?" +msgstr "Have you forgotten your password?" + +#: .\contrib\admin\templates\admin\login.html.py:25 +#: .\contrib\admin\views\decorators.py:24 +msgid "Log in" +msgstr "دخول" + +#: .\contrib\admin\templates\admin\object_history.html.py:18 +msgid "Date/time" +msgstr "التاريخ/الوقت" + +#: .\contrib\admin\templates\admin\object_history.html.py:19 +msgid "User" +msgstr "المستخدم" + +#: .\contrib\admin\templates\admin\object_history.html.py:20 +msgid "Action" +msgstr "العملية" + +#: .\contrib\admin\templates\admin\object_history.html.py:26 +msgid "DATE_WITH_TIME_FULL" +msgstr "" + +#: .\contrib\admin\templates\admin\object_history.html.py:36 +msgid "This object doesn't have a change history. It probably wasn't added via this admin site." +msgstr "هذا العنصر لا يملك تاريخ تغييرات، على الأغلب أن هذا العنصر لم يتم انشاءه عبر نظام الإدارة هذا." + +#: .\contrib\admin\templates\admin\pagination.html.py:10 +msgid "Show all" +msgstr "عرض الكل" + +#: .\contrib\admin\templates\admin\search_form.html.py:8 +msgid "Go" +msgstr "انطلق" + +#: .\contrib\admin\templates\admin\search_form.html.py:10 +#, python-format +msgid "1 result" +msgid_plural "%(counter)s results" +msgstr[0] "نتيحة واحدة" +msgstr[1] "نتيجتان" +msgstr[2] "%(counter)s نتائج" +msgstr[3] "%(counter)s نتيحة" + +#: .\contrib\admin\templates\admin\search_form.html.py:10 +#, python-format +msgid "%(full_result_count)s total" +msgstr "المجموع %(full_result_count)s" + +#: .\contrib\admin\templates\admin\submit_line.html.py:4 +msgid "Save as new" +msgstr "حفظ كجديد" + +#: .\contrib\admin\templates\admin\submit_line.html.py:5 +msgid "Save and add another" +msgstr "حفظ وإضافة آخر" + +#: .\contrib\admin\templates\admin\submit_line.html.py:6 +msgid "Save and continue editing" +msgstr "حفظ واستمرار التعديل" + +#: .\contrib\admin\templates\admin\submit_line.html.py:7 +msgid "Save" +msgstr "حفظ" + +#: .\contrib\admin\templates\admin_doc\bookmarklets.html.py:3 +msgid "Bookmarklets" +msgstr "أوامر المفضلة" + +#: .\contrib\admin\templates\admin_doc\bookmarklets.html.py:5 +msgid "Documentation bookmarklets" +msgstr "أوامر مفضلة التعليمات" + +#: .\contrib\admin\templates\admin_doc\bookmarklets.html.py:9 +msgid "" +"\n" +"

      To install bookmarklets, drag the link to your bookmarks\n" +"toolbar, or right-click the link and add it to your bookmarks. Now you can\n" +"select the bookmarklet from any page in the site. Note that some of these\n" +"bookmarklets require you to be viewing the site from a computer designated\n" +"as \"internal\" (talk to your system administrator if you aren't sure if\n" +"your computer is \"internal\").

      \n" +msgstr "" +"\n" +"

      لتركيب أوامر المفضلة، قم بسحب الوصلة إلى\n" +"شريط أدات المفضلات في متصفحك، أو قم بالضغط عليها بالزر الأيمن وأضفها إلى مفضلاتك.\n" +"سيمكنك الآن أن اختيار أوامر المفضلة من أي صفحة في الموقع، لاحظ بأن بعض\n" +"أوامر المفضلة هذه معدة لتعمل على أجهزة كمبيوتر تعتبر على أنها \"داخلية\"\n" +"(تحدث إلى مسؤول النظم إذا لم تكن متأكدا ما إذا كان كمبيوتر يعتبر \"داخليا\").

      \n" + +#: .\contrib\admin\templates\admin_doc\bookmarklets.html.py:19 +msgid "Documentation for this page" +msgstr "التعليمات لهذه الصفحة" + +#: .\contrib\admin\templates\admin_doc\bookmarklets.html.py:20 +msgid "Jumps you from any page to the documentation for the view that generates that page." +msgstr "ينتقل بك من أي صفحة إلى تعليمات العرض الذي أنشأ هذه الصفحة." + +#: .\contrib\admin\templates\admin_doc\bookmarklets.html.py:22 +msgid "Show object ID" +msgstr "عرض معرف الكائن" + +#: .\contrib\admin\templates\admin_doc\bookmarklets.html.py:23 +msgid "Shows the content-type and unique ID for pages that represent a single object." +msgstr "عرض نوع البيانات والمعرف الفريد للصفحات التي تمثل كائنا واحدا." + +#: .\contrib\admin\templates\admin_doc\bookmarklets.html.py:25 +msgid "Edit this object (current window)" +msgstr "تعديل هذا الكائن (النافذة الحالية)" + +#: .\contrib\admin\templates\admin_doc\bookmarklets.html.py:26 +msgid "Jumps to the admin page for pages that represent a single object." +msgstr "ينتقل بك إلى صفحة الإدارة للصفحات التي تمثل كائنا واحدا." + +#: .\contrib\admin\templates\admin_doc\bookmarklets.html.py:28 +msgid "Edit this object (new window)" +msgstr "تعديل هذا العنصر (نافذة جديدة)" + +#: .\contrib\admin\templates\admin_doc\bookmarklets.html.py:29 +msgid "As above, but opens the admin page in a new window." +msgstr "كما سبق، لكن يفتح صفحة الإدارة في نافذة جديدة." + +#: .\contrib\admin\templates\registration\logged_out.html.py:8 +msgid "Thanks for spending some quality time with the Web site today." +msgstr "شكرا لك على قضائك بعض الوقت مع الموقع اليوم." + +#: .\contrib\admin\templates\registration\logged_out.html.py:10 +msgid "Log in again" +msgstr "دخول مرة أخرى" + +#: .\contrib\admin\templates\registration\password_change_done.html.py:4 +#: .\contrib\admin\templates\registration\password_change_form.html.py:4 +#: .\contrib\admin\templates\registration\password_change_form.html.py:6 +#: .\contrib\admin\templates\registration\password_change_form.html.py:10 +msgid "Password change" +msgstr "تغيير كلمة المرور" + +#: .\contrib\admin\templates\registration\password_change_done.html.py:6 +#: .\contrib\admin\templates\registration\password_change_done.html.py:10 +msgid "Password change successful" +msgstr "تم تغيير كلمة المرور بنجاح" + +#: .\contrib\admin\templates\registration\password_change_done.html.py:12 +msgid "Your password was changed." +msgstr "لقد تغيرت كلمة مرورك." + +#: .\contrib\admin\templates\registration\password_change_form.html.py:12 +msgid "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." +msgstr "الرجاء ادخال كلمة مرورك القديمة، زيادة في الأمان، ثم ادخل كلمة مرورك الجديدة مرتين لنكون متأكدين من أنك كتبتها بصورة صحيحة." + +#: .\contrib\admin\templates\registration\password_change_form.html.py:17 +msgid "Old password:" +msgstr "كلمة المرور القديمة:" + +#: .\contrib\admin\templates\registration\password_change_form.html.py:19 +msgid "New password:" +msgstr "كلمة المرور الجديدة:" + +#: .\contrib\admin\templates\registration\password_change_form.html.py:21 +msgid "Confirm password:" +msgstr "تأكيد كلمة المرور:" + +#: .\contrib\admin\templates\registration\password_change_form.html.py:23 +msgid "Change my password" +msgstr "تغيير كلمة المرور الخاصة بي" + +#: .\contrib\admin\templates\registration\password_reset_done.html.py:4 +#: .\contrib\admin\templates\registration\password_reset_form.html.py:4 +#: .\contrib\admin\templates\registration\password_reset_form.html.py:6 +#: .\contrib\admin\templates\registration\password_reset_form.html.py:10 +msgid "Password reset" +msgstr "اعادة ضبط كلمة المرور" + +#: .\contrib\admin\templates\registration\password_reset_done.html.py:6 +#: .\contrib\admin\templates\registration\password_reset_done.html.py:10 +msgid "Password reset successful" +msgstr "تمت عملية اعادة ضبط كلمة المرور بنجاح" + +#: .\contrib\admin\templates\registration\password_reset_done.html.py:12 +msgid "We've e-mailed a new password to the e-mail address you submitted. You should be receiving it shortly." +msgstr "لقد قمنا بارسال كلمة مرور جديدة إلى عنوان البريد الإلكتروني الذي أدخلتها، ستصلك قريبا إن شاء الله." + +#: .\contrib\admin\templates\registration\password_reset_email.html.py:2 +msgid "You're receiving this e-mail because you requested a password reset" +msgstr "لقد وصلتك رسالة البريد الإلكتروني هذه لأنك طلبت إعادة ضبط كلمة المرور." + +#: .\contrib\admin\templates\registration\password_reset_email.html.py:3 +#, python-format +msgid "for your user account at %(site_name)s" +msgstr "لحسابك المستخدم الخاص بك في %(site_name)s" + +#: .\contrib\admin\templates\registration\password_reset_email.html.py:5 +#, python-format +msgid "Your new password is: %(new_password)s" +msgstr "كلمة مرورك الجديدة هي: %(new_password)s" + +#: .\contrib\admin\templates\registration\password_reset_email.html.py:7 +msgid "Feel free to change this password by going to this page:" +msgstr "يمكنك تغيير كلمة المرور هذه بالذهاب إلى هذه الصفحة:" + +#: .\contrib\admin\templates\registration\password_reset_email.html.py:11 +msgid "Your username, in case you've forgotten:" +msgstr "اسم المستخدم الخاص بك، في حال كنت قد نسيته:" + +#: .\contrib\admin\templates\registration\password_reset_email.html.py:13 +msgid "Thanks for using our site!" +msgstr "شكرا لاستخدامك لموقعنا!" + +#: .\contrib\admin\templates\registration\password_reset_email.html.py:15 +#, python-format +msgid "The %(site_name)s team" +msgstr "فريق %(site_name)s" + +#: .\contrib\admin\templates\registration\password_reset_form.html.py:12 +msgid "Forgotten your password? Enter your e-mail address below, and we'll reset your password and e-mail the new one to you." +msgstr "نسيت كلمة المرور الخاصة بك؟ قم بادخال عنوان بريدك الإلكتروني بالأسفل وسنقوم باعادة ضبط كلمة المرور الخاصة بك وارسال كلمة المرور الجديدة إليك عبر البريد الإلكتروني." + +#: .\contrib\admin\templates\registration\password_reset_form.html.py:16 +msgid "E-mail address:" +msgstr "عنوان البريد الإلكتروني:" + +#: .\contrib\admin\templates\registration\password_reset_form.html.py:16 +msgid "Reset my password" +msgstr "اعادة ضبط كلمة المرور" + +#: .\contrib\admin\templates\widget\date_time.html.py:3 +msgid "Date:" +msgstr "التاريخ:" + +#: .\contrib\admin\templates\widget\date_time.html.py:4 +msgid "Time:" +msgstr "الوقت:" + +#: .\contrib\admin\templates\widget\file.html.py:2 +msgid "Currently:" +msgstr "حاليا:" + +#: .\contrib\admin\templates\widget\file.html.py:3 +msgid "Change:" +msgstr "تغيير:" + +#: .\contrib\admin\templatetags\admin_list.py:230 +msgid "All dates" +msgstr "كافة التواريخ" + +#: .\contrib\admin\views\decorators.py:10 +#: .\contrib\auth\forms.py:37 +msgid "Please enter a correct username and password. Note that both fields are case-sensitive." +msgstr "الرجاء ادخال اسم مستخدم وكلمة مرور صحيحين، الرجاء الانتباه إلى أن كلا الحقلين حساس لحالة الأحرف من حيث كونها كبيرة أو صغيرة." + +#: .\contrib\admin\views\decorators.py:62 +msgid "Please log in again, because your session has expired. Don't worry: Your submission has been saved." +msgstr "الرجاء الدخول مرة أخرى لأن جلستك انتهت، لا تقلق: البيانات التي قمت بارسالها حفظت." + +#: .\contrib\admin\views\decorators.py:69 +msgid "Looks like your browser isn't configured to accept cookies. Please enable cookies, reload this page, and try again." +msgstr "يبدو بأن متصفحك غير معد لقبول الكوكيز، قم بتفعيل الكوكيز من فضلك ثم تحديث هذه الصفحة والمحاولة مرة أخرى." + +#: .\contrib\admin\views\decorators.py:83 +msgid "Usernames cannot contain the '@' character." +msgstr "اسم المستخدم يجب أن لا يحتوي على علامة '@'." + +#: .\contrib\admin\views\decorators.py:85 +#, python-format +msgid "Your e-mail address is not your username. Try '%s' instead." +msgstr "بريدك الإلكتروني ليس اسم المستخدم الخاص بك، جرب استخدام '%s' بدلا من ذلك." + +#: .\contrib\admin\views\doc.py:291 +#: .\contrib\admin\views\doc.py:301 +#: .\contrib\admin\views\doc.py:303 +#: .\contrib\admin\views\doc.py:309 +#: .\contrib\admin\views\doc.py:310 +#: .\contrib\admin\views\doc.py:312 +msgid "Integer" +msgstr "عدد صحيح" + +#: .\contrib\admin\views\doc.py:292 +msgid "Boolean (Either True or False)" +msgstr "ثنائي (إما صح أو خطأ)" + +#: .\contrib\admin\views\doc.py:293 +#: .\contrib\admin\views\doc.py:311 +#, python-format +msgid "String (up to %(maxlength)s)" +msgstr "سلسلة نصية (تصل إلى %(maxlength)s)" + +#: .\contrib\admin\views\doc.py:294 +msgid "Comma-separated integers" +msgstr "أرقام صحيحة مفصولة بفواصل comma" + +#: .\contrib\admin\views\doc.py:295 +msgid "Date (without time)" +msgstr "التاريخ (بدون الوقت)" + +#: .\contrib\admin\views\doc.py:296 +msgid "Date (with time)" +msgstr "التاريخ (مع الوقت)" + +#: .\contrib\admin\views\doc.py:297 +msgid "E-mail address" +msgstr "عنوان البريد الإلكتروني" + +#: .\contrib\admin\views\doc.py:298 +#: .\contrib\admin\views\doc.py:299 +#: .\contrib\admin\views\doc.py:302 +msgid "File path" +msgstr "مسار الملف" + +#: .\contrib\admin\views\doc.py:300 +msgid "Decimal number" +msgstr "رقم عشري" + +#: .\contrib\admin\views\doc.py:304 +#: .\contrib\comments\models.py:85 +msgid "IP address" +msgstr "عنوان IP" + +#: .\contrib\admin\views\doc.py:306 +msgid "Boolean (Either True, False or None)" +msgstr "ثنائي (إما صح أو خطأ أو لاشيء)" + +#: .\contrib\admin\views\doc.py:307 +msgid "Relation to parent model" +msgstr "العلاقة بالنموذج الأب" + +#: .\contrib\admin\views\doc.py:308 +msgid "Phone number" +msgstr "رقم هاتف" + +#: .\contrib\admin\views\doc.py:313 +msgid "Text" +msgstr "نص" + +#: .\contrib\admin\views\doc.py:314 +msgid "Time" +msgstr "وقت" + +#: .\contrib\admin\views\doc.py:315 +#: .\contrib\flatpages\models.py:7 +msgid "URL" +msgstr "وصلة" + +#: .\contrib\admin\views\doc.py:316 +msgid "U.S. state (two uppercase letters)" +msgstr "ولاية أمريكية (حرفان كبيران)" + +#: .\contrib\admin\views\doc.py:317 +msgid "XML text" +msgstr "نص XML" + +#: .\contrib\admin\views\main.py:226 +msgid "Site administration" +msgstr "إدارة الموقع" + +#: .\contrib\admin\views\main.py:260 +#, python-format +msgid "The %(name)s \"%(obj)s\" was added successfully." +msgstr "تم اضافة %(name)s \"%(obj)s\" بنجاح." + +#: .\contrib\admin\views\main.py:264 +#: .\contrib\admin\views\main.py:348 +msgid "You may edit it again below." +msgstr "يمكنك تعديله مجددا في الأسفل." + +#: .\contrib\admin\views\main.py:272 +#: .\contrib\admin\views\main.py:357 +#, python-format +msgid "You may add another %s below." +msgstr "يمكنك إضافة %s آخر بالأسفل." + +#: .\contrib\admin\views\main.py:290 +#, python-format +msgid "Add %s" +msgstr "اضافة %s" + +#: .\contrib\admin\views\main.py:336 +#, python-format +msgid "Added %s." +msgstr "اضاف %s." + +#: .\contrib\admin\views\main.py:336 +#: .\contrib\admin\views\main.py:338 +#: .\contrib\admin\views\main.py:340 +msgid "and" +msgstr "و" + +#: .\contrib\admin\views\main.py:338 +#, python-format +msgid "Changed %s." +msgstr "غير %s." + +#: .\contrib\admin\views\main.py:340 +#, python-format +msgid "Deleted %s." +msgstr "حذف %s." + +#: .\contrib\admin\views\main.py:343 +msgid "No fields changed." +msgstr "لم يتم تغيير أية حقول." + +#: .\contrib\admin\views\main.py:346 +#, python-format +msgid "The %(name)s \"%(obj)s\" was changed successfully." +msgstr "تم تغيير %(name)s \"%(obj)s\" بنجاح." + +#: .\contrib\admin\views\main.py:354 +#, python-format +msgid "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." +msgstr "تم اضافة %(name)s \"%(obj)s\" بنجاح، يمكنك تعديله مرة أخرى بالأسفل." + +#: .\contrib\admin\views\main.py:392 +#, python-format +msgid "Change %s" +msgstr "تغيير %s" + +#: .\contrib\admin\views\main.py:474 +#, python-format +msgid "One or more %(fieldname)s in %(name)s: %(obj)s" +msgstr "%(fieldname)s واحد أو أكثر في %(name)s: %(obj)s" + +#: .\contrib\admin\views\main.py:479 +#, python-format +msgid "One or more %(fieldname)s in %(name)s:" +msgstr "%(fieldname)s واحد أو أكثر في %(name)s:" + +#: .\contrib\admin\views\main.py:512 +#, python-format +msgid "The %(name)s \"%(obj)s\" was deleted successfully." +msgstr "تم حذف %(name)s \"%(obj)s\" بنجاح." + +#: .\contrib\admin\views\main.py:515 +msgid "Are you sure?" +msgstr "هل أنت متأكد؟" + +#: .\contrib\admin\views\main.py:537 +#, python-format +msgid "Change history: %s" +msgstr "تاريخ التغيير: %s" + +#: .\contrib\admin\views\main.py:571 +#, python-format +msgid "Select %s" +msgstr "اختر %s" + +#: .\contrib\admin\views\main.py:571 +#, python-format +msgid "Select %s to change" +msgstr "اختر %s لتغييره" + +#: .\contrib\admin\views\main.py:747 +msgid "Database error" +msgstr "خطـأ في قاعدة البيانات" + +#: .\contrib\auth\forms.py:30 +msgid "Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in." +msgstr "يبدو بأن الكوكيز غير مفعله في متصفحك، الكوكيز مطلوبة للتمكن من الدخول." + +#: .\contrib\auth\forms.py:39 +msgid "This account is inactive." +msgstr "هذا الحساب غير فعال." + +#: .\contrib\auth\models.py:37 +#: .\contrib\auth\models.py:56 +msgid "name" +msgstr "الاسم" + +#: .\contrib\auth\models.py:39 +msgid "codename" +msgstr "الاسم الرمزي" + +#: .\contrib\auth\models.py:41 +msgid "permission" +msgstr "الصلاحية" + +#: .\contrib\auth\models.py:42 +#: .\contrib\auth\models.py:57 +msgid "permissions" +msgstr "الصلاحيات" + +#: .\contrib\auth\models.py:59 +msgid "group" +msgstr "المجموعة" + +#: .\contrib\auth\models.py:60 +#: .\contrib\auth\models.py:99 +msgid "groups" +msgstr "المجموعات" + +#: .\contrib\auth\models.py:89 +msgid "username" +msgstr "اسم المستخدم" + +#: .\contrib\auth\models.py:89 +msgid "Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)." +msgstr "مطلوب. 30 خانة أو أقل. خانات حرف رقمية فقط (أحرف، أرقام والشرطة السفلية)." + +#: .\contrib\auth\models.py:90 +msgid "first name" +msgstr "الاسم الأول" + +#: .\contrib\auth\models.py:91 +msgid "last name" +msgstr "الاسم الأخير" + +#: .\contrib\auth\models.py:92 +msgid "e-mail address" +msgstr "عنوان البريد الإلكتروني" + +#: .\contrib\auth\models.py:93 +msgid "password" +msgstr "كلمة المرور" + +#: .\contrib\auth\models.py:93 +msgid "Use '[algo]$[salt]$[hexdigest]'" +msgstr "استخدم '[algo]$[salt]$[hexdigest]'" + +#: .\contrib\auth\models.py:94 +msgid "staff status" +msgstr "حالة الطاقم" + +#: .\contrib\auth\models.py:94 +msgid "Designates whether the user can log into this admin site." +msgstr "يحدد ما إذا كان المستخدم يستطيع الدخول إلى موقع الإدارة هذا." + +#: .\contrib\auth\models.py:95 +msgid "active" +msgstr "فعال" + +#: .\contrib\auth\models.py:95 +msgid "Designates whether this user can log into the Django admin. Unselect this instead of deleting accounts." +msgstr "يحدد ما إذا كان المستخدم يستطيع الدخول إلى لوحة تحكم جانغو، قم بتحديد هذا الخيار بدلا من حذف حسابات المستخدمين." + +#: .\contrib\auth\models.py:96 +msgid "superuser status" +msgstr "حالة المستخدم بالقوى الخارقة" + +#: .\contrib\auth\models.py:96 +msgid "Designates that this user has all permissions without explicitly assigning them." +msgstr "حدد بأن هذا المستخدم يمتلك كافة الصلاحيات دون الحاجة لتحديدها له تصريحا." + +#: .\contrib\auth\models.py:97 +msgid "last login" +msgstr "آخر عملية دخول" + +#: .\contrib\auth\models.py:98 +msgid "date joined" +msgstr "تاريخ الانضمام" + +#: .\contrib\auth\models.py:100 +msgid "In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in." +msgstr "بالإضافة إلى الصلاحيات المحددة للمستخدم يدويا، فإن المستخدم يحصل أيضا على كافة صلاحيات المجموعة التي ينتمي إليها." + +#: .\contrib\auth\models.py:101 +msgid "user permissions" +msgstr "صلاحيات المستخدم" + +#: .\contrib\auth\models.py:104 +msgid "user" +msgstr "المستخدم" + +#: .\contrib\auth\models.py:105 +msgid "users" +msgstr "المستخدمين" + +#: .\contrib\auth\models.py:110 +msgid "Personal info" +msgstr "المعلومات الشخصية" + +#: .\contrib\auth\models.py:111 +msgid "Permissions" +msgstr "الصلاحيات" + +#: .\contrib\auth\models.py:112 +msgid "Important dates" +msgstr "تواريخ مهمة" + +#: .\contrib\auth\models.py:113 +msgid "Groups" +msgstr "المجموعات" + +#: .\contrib\auth\models.py:250 +msgid "message" +msgstr "رسالة" + +#: .\contrib\auth\views.py:40 +msgid "Logged out" +msgstr "خروج" + +#: .\contrib\comments\models.py:67 +#: .\contrib\comments\models.py:166 +msgid "object ID" +msgstr "معرف العنصر" + +#: .\contrib\comments\models.py:68 +msgid "headline" +msgstr "عنوان" + +#: .\contrib\comments\models.py:69 +#: .\contrib\comments\models.py:90 +#: .\contrib\comments\models.py:167 +msgid "comment" +msgstr "تعليق" + +#: .\contrib\comments\models.py:70 +msgid "rating #1" +msgstr "تقييم #1" + +#: .\contrib\comments\models.py:71 +msgid "rating #2" +msgstr "تقييم #2" + +#: .\contrib\comments\models.py:72 +msgid "rating #3" +msgstr "تقييم #3" + +#: .\contrib\comments\models.py:73 +msgid "rating #4" +msgstr "تقييم #4" + +#: .\contrib\comments\models.py:74 +msgid "rating #5" +msgstr "تقييم #5" + +#: .\contrib\comments\models.py:75 +msgid "rating #6" +msgstr "تقييم #8" + +#: .\contrib\comments\models.py:76 +msgid "rating #7" +msgstr "تقييم #7" + +#: .\contrib\comments\models.py:77 +msgid "rating #8" +msgstr "تقييم #8" + +#: .\contrib\comments\models.py:82 +msgid "is valid rating" +msgstr "تقييم صالح" + +#: .\contrib\comments\models.py:83 +#: .\contrib\comments\models.py:169 +msgid "date/time submitted" +msgstr "تم ارسال التاريخ/الوقت" + +#: .\contrib\comments\models.py:84 +#: .\contrib\comments\models.py:170 +msgid "is public" +msgstr "عام" + +#: .\contrib\comments\models.py:86 +msgid "is removed" +msgstr "محذوف" + +#: .\contrib\comments\models.py:86 +msgid "Check this box if the comment is inappropriate. A \"This comment has been removed\" message will be displayed instead." +msgstr "قم بتحديد هذا المربع إذا كان التعليق غير لائق، سيتم عرض الرسالة \"تم حذف هذا التعليق\" بدلا منه." + +#: .\contrib\comments\models.py:91 +msgid "comments" +msgstr "تعليقات" + +#: .\contrib\comments\models.py:131 +#: .\contrib\comments\models.py:207 +msgid "Content object" +msgstr "عنصر محتوى" + +#: .\contrib\comments\models.py:159 +#, python-format +msgid "" +"Posted by %(user)s at %(date)s\n" +"\n" +"%(comment)s\n" +"\n" +"http://%(domain)s%(url)s" +msgstr "" +"أرسلت بواسطة %(user)s في %(date)s\n" +"\n" +"%(comment)s\n" +"\n" +"http://%(domain)s%(url)s" + +#: .\contrib\comments\models.py:168 +msgid "person's name" +msgstr "اسم الشخص" + +#: .\contrib\comments\models.py:171 +msgid "ip address" +msgstr "عنوان ip" + +#: .\contrib\comments\models.py:173 +msgid "approved by staff" +msgstr "موافق عليه من قبل الطاقم" + +#: .\contrib\comments\models.py:176 +msgid "free comment" +msgstr "تعليق حر" + +#: .\contrib\comments\models.py:177 +msgid "free comments" +msgstr "تعليقات حرة" + +#: .\contrib\comments\models.py:233 +msgid "score" +msgstr "الدرجة" + +#: .\contrib\comments\models.py:234 +msgid "score date" +msgstr "تاريخ الدرجة" + +#: .\contrib\comments\models.py:237 +msgid "karma score" +msgstr "درجة الكارما" + +#: .\contrib\comments\models.py:238 +msgid "karma scores" +msgstr "درجات الكارما" + +#: .\contrib\comments\models.py:242 +#, python-format +msgid "%(score)d rating by %(user)s" +msgstr "تقييم %(score)d بواسطة %(user)s" + +#: .\contrib\comments\models.py:258 +#, python-format +msgid "" +"This comment was flagged by %(user)s:\n" +"\n" +"%(text)s" +msgstr "" +"هذا التعليق تم تعليمه بواسطة %(user)s:\n" +"\n" +"%(text)s" + +#: .\contrib\comments\models.py:265 +msgid "flag date" +msgstr "تاريخ التعليم" + +#: .\contrib\comments\models.py:268 +msgid "user flag" +msgstr "علامة مستخدم" + +#: .\contrib\comments\models.py:269 +msgid "user flags" +msgstr "علامات المستخدم" + +#: .\contrib\comments\models.py:273 +#, python-format +msgid "Flag by %r" +msgstr "علامة بواسطة %r" + +#: .\contrib\comments\models.py:278 +msgid "deletion date" +msgstr "تاريخ الحذف" + +#: .\contrib\comments\models.py:280 +msgid "moderator deletion" +msgstr "حذف المراقب" + +#: .\contrib\comments\models.py:281 +msgid "moderator deletions" +msgstr "حذوفات المراقب" + +#: .\contrib\comments\models.py:285 +#, python-format +msgid "Moderator deletion by %r" +msgstr "حذف المراقب بواسطة %r" + +#: .\contrib\comments\templates\comments\form.html.py:6 +msgid "Forgotten your password?" +msgstr "نسيت كلمة المرور؟" + +#: .\contrib\comments\templates\comments\form.html.py:12 +msgid "Ratings" +msgstr "التقييمات" + +#: .\contrib\comments\templates\comments\form.html.py:12 +#: .\contrib\comments\templates\comments\form.html.py:23 +msgid "Required" +msgstr "مطلوب" + +#: .\contrib\comments\templates\comments\form.html.py:12 +#: .\contrib\comments\templates\comments\form.html.py:23 +msgid "Optional" +msgstr "اختياري" + +#: .\contrib\comments\templates\comments\form.html.py:23 +msgid "Post a photo" +msgstr "ارسال صورة" + +#: .\contrib\comments\templates\comments\form.html.py:28 +#: .\contrib\comments\templates\comments\freeform.html.py:5 +msgid "Comment:" +msgstr "تعليق:" + +#: .\contrib\comments\templates\comments\form.html.py:34 +#: .\contrib\comments\templates\comments\freeform.html.py:9 +msgid "Preview comment" +msgstr "استعراض التعليق" + +#: .\contrib\comments\templates\comments\freeform.html.py:4 +msgid "Your name:" +msgstr "اسمك:" + +#: .\contrib\comments\views\comments.py:27 +msgid "This rating is required because you've entered at least one other rating." +msgstr "هذا التقييم مطلوب لأنك قمت بادخال تقييم واحد على الأقل." + +#: .\contrib\comments\views\comments.py:111 +#, python-format +msgid "" +"This comment was posted by a user who has posted fewer than %(count)s comment:\n" +"\n" +"%(text)s" +msgid_plural "" +"This comment was posted by a user who has posted fewer than %(count)s comments:\n" +"\n" +"%(text)s" +msgstr[0] "" +"هذا التعليق كتب بواسطة شخص لديه أقل من تعليق واحد:\n" +"\n" +"%(text)s" +msgstr[1] "" +"هذا التعليق كتب بواسطة شخص لديه أقل من تعليقان:\n" +"\n" +"%(text)s" +msgstr[2] "" +"هذا التعليق كتب بواسطة شخص لديه أقل من %(count)s تعليقات:\n" +"\n" +"%(text)s" +msgstr[3] "" +"هذا التعليق كتب بواسطة شخص لديه أقل من %(count)s تعليق:\n" +"\n" +"%(text)s" + +#: .\contrib\comments\views\comments.py:116 +#, python-format +msgid "" +"This comment was posted by a sketchy user:\n" +"\n" +"%(text)s" +msgstr "" +"هذا التعليق كتب بواسطة عضو سطحي:\n" +"\n" +"%(text)s" + +#: .\contrib\comments\views\comments.py:188 +#: .\contrib\comments\views\comments.py:280 +msgid "Only POSTs are allowed" +msgstr "يسمح باستخدام POST فقط" + +#: .\contrib\comments\views\comments.py:192 +#: .\contrib\comments\views\comments.py:284 +msgid "One or more of the required fields wasn't submitted" +msgstr "لم يتم ارسال واحد أو أكثر من الحقول المطلوبة." + +#: .\contrib\comments\views\comments.py:196 +#: .\contrib\comments\views\comments.py:286 +msgid "Somebody tampered with the comment form (security violation)" +msgstr "شخص ما قام بالتلاعب بنموذج التعليق (انتهاك أمني)" + +#: .\contrib\comments\views\comments.py:206 +#: .\contrib\comments\views\comments.py:292 +msgid "The comment form had an invalid 'target' parameter -- the object ID was invalid" +msgstr "نموذج التعليق احتوى 'هدف' غير صحيح -- معرف الكائن كان غير صحيحا" + +#: .\contrib\comments\views\comments.py:257 +#: .\contrib\comments\views\comments.py:321 +msgid "The comment form didn't provide either 'preview' or 'post'" +msgstr "نموذج التعليق لم يحدد أيا من 'استعراض' أو 'ارسال'" + +#: .\contrib\comments\views\karma.py:19 +msgid "Anonymous users cannot vote" +msgstr "لا يمكن للمستخدمين المجهولين التصويت" + +#: .\contrib\comments\views\karma.py:23 +msgid "Invalid comment ID" +msgstr "معرف التعليق غير صحيح" + +#: .\contrib\comments\views\karma.py:25 +msgid "No voting for yourself" +msgstr "لا يمكنك التصويت لنفسك" + +#: .\contrib\contenttypes\models.py:20 +msgid "python model class name" +msgstr "اسم صنف النموذج في python" + +#: .\contrib\contenttypes\models.py:23 +msgid "content type" +msgstr "نوع البيانات" + +#: .\contrib\contenttypes\models.py:24 +msgid "content types" +msgstr "أنواع البيانات" + +#: .\contrib\flatpages\models.py:8 +msgid "Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "مثال: '/about/contact/'. تأكد من وضع شرطات في البداية والنهاية." + +#: .\contrib\flatpages\models.py:9 +msgid "title" +msgstr "العنوان" + +#: .\contrib\flatpages\models.py:10 +msgid "content" +msgstr "المحتوى" + +#: .\contrib\flatpages\models.py:11 +msgid "enable comments" +msgstr "السماح بالتعليقات" + +#: .\contrib\flatpages\models.py:12 +msgid "template name" +msgstr "اسم القالب" + +#: .\contrib\flatpages\models.py:13 +msgid "Example: 'flatpages/contact_page'. If this isn't provided, the system will use 'flatpages/default'." +msgstr "مثال: 'flatpages/contact_page'. إذا لم يتم تحديده فإن النظام سيقوم باستخدام 'flatpages/default'." + +#: .\contrib\flatpages\models.py:14 +msgid "registration required" +msgstr "التسجيل مطلوب" + +#: .\contrib\flatpages\models.py:14 +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "إذا كان هذا الخيار محددا، فإن المستخدمين الداخلين فقط سيتمكنون من مشاهدة الصفحة." + +#: .\contrib\flatpages\models.py:18 +msgid "flat page" +msgstr "صفحة مسطحة" + +#: .\contrib\flatpages\models.py:19 +msgid "flat pages" +msgstr "صفحات مسطحة" + +#: .\contrib\redirects\models.py:7 +msgid "redirect from" +msgstr "نموذج إعادة توجيه" + +#: .\contrib\redirects\models.py:8 +msgid "This should be an absolute path, excluding the domain name. Example: '/events/search/'." +msgstr "يجب أن يكون هذا مسارا مطلقا وبدون اسم النطاق. مثال: '/events/search/'." + +#: .\contrib\redirects\models.py:9 +msgid "redirect to" +msgstr "إعادة توجيه إلى" + +#: .\contrib\redirects\models.py:10 +msgid "This can be either an absolute path (as above) or a full URL starting with 'http://'." +msgstr "يجب أن يكون هذا مسارا مطلقا (كما في الذي فوقه) عنوانا كاملا يبدأ بالمقطع 'http://'." + +#: .\contrib\redirects\models.py:13 +msgid "redirect" +msgstr "إعادة توجيه" + +#: .\contrib\redirects\models.py:14 +msgid "redirects" +msgstr "إعادات توجيه" + +#: .\contrib\sessions\models.py:41 +msgid "session key" +msgstr "مفتاح الجلسة" + +#: .\contrib\sessions\models.py:42 +msgid "session data" +msgstr "بيانات الجلسة" + +#: .\contrib\sessions\models.py:43 +msgid "expire date" +msgstr "تاريخ الانتهاء" + +#: .\contrib\sessions\models.py:47 +msgid "session" +msgstr "جلسة" + +#: .\contrib\sessions\models.py:48 +msgid "sessions" +msgstr "جلسات" + +#: .\contrib\sites\models.py:10 +msgid "domain name" +msgstr "اسم النطاق" + +#: .\contrib\sites\models.py:11 +msgid "display name" +msgstr "اسم العرض" + +#: .\contrib\sites\models.py:15 +msgid "site" +msgstr "موقع" + +#: .\contrib\sites\models.py:16 +msgid "sites" +msgstr "مواقع" + +#: .\core\validators.py:63 +msgid "This value must contain only letters, numbers and underscores." +msgstr "هذه القيمة يجب أن تحتوي فقط على الأحرف والأرقام والشرطة السفلية." + +#: .\core\validators.py:67 +msgid "This value must contain only letters, numbers, underscores, dashes or slashes." +msgstr "هذه القيمة يجب أن تحتوي فقط على الأحرف والأرقام والشرطات السفلية والشرطة العادية والشرطات المائلة." + +#: .\core\validators.py:75 +msgid "Uppercase letters are not allowed here." +msgstr "الحروف الكبيرة غير مسموح بها هنا." + +#: .\core\validators.py:79 +msgid "Lowercase letters are not allowed here." +msgstr "الحروف الصغيرة غير مسموح بها هنا." + +#: .\core\validators.py:86 +msgid "Enter only digits separated by commas." +msgstr "أدخل أرقاما فقط مفصول بينها بفواصل comma." + +#: .\core\validators.py:98 +msgid "Enter valid e-mail addresses separated by commas." +msgstr "أدخل عناوين بريد إلكتروني صالحة مفصول بينها بفواصل comma." + +#: .\core\validators.py:102 +msgid "Please enter a valid IP address." +msgstr "أدخل عنوان IP صالح من فضلك." + +#: .\core\validators.py:106 +msgid "Empty values are not allowed here." +msgstr "القيم الفارغة غير مسموح بها هنا." + +#: .\core\validators.py:110 +msgid "Non-numeric characters aren't allowed here." +msgstr "الخانات غير الرقمية غير مسموح بها هنا." + +#: .\core\validators.py:114 +msgid "This value can't be comprised solely of digits." +msgstr "لا يمكن أن تكون القيمة مكونة من الأرقام فقط." + +#: .\core\validators.py:119 +msgid "Enter a whole number." +msgstr "أدخل رقما صحيحا." + +#: .\core\validators.py:123 +msgid "Only alphabetical characters are allowed here." +msgstr "فقط الخانات الحرفية مسموح بها هنا." + +#: .\core\validators.py:127 +#: .\db\models\fields\__init__.py:412 +msgid "Enter a valid date in YYYY-MM-DD format." +msgstr "أدخل تاريخا صحيحا بتنسيق YYYY-MM-DD." + +#: .\core\validators.py:131 +msgid "Enter a valid time in HH:MM format." +msgstr "أدخل وقتا صحيحا بتنسيق HH:MM." + +#: .\core\validators.py:135 +#: .\db\models\fields\__init__.py:474 +msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format." +msgstr "أدخل تاريخ/وقت صحيحين بتنسيق YYYY-MM-DD HH:MM." + +#: .\core\validators.py:139 +msgid "Enter a valid e-mail address." +msgstr "أدخل عنوان بريد إلكتروني صحيح." + +#: .\core\validators.py:151 +#: .\core\validators.py:379 +#: .\forms\__init__.py:659 +msgid "No file was submitted. Check the encoding type on the form." +msgstr "لم يتم ارسال ملف، الرجاء التأكد من نوع ترميز (encoding type) النموذج." + +#: .\core\validators.py:155 +msgid "Upload a valid image. The file you uploaded was either not an image or a corrupted image." +msgstr "قم برفع صورة صالحة، الملف الذي قمت برفعه إما أنه ليس ملفا لصورة أو أنه ملف معطوب." + +#: .\core\validators.py:162 +#, python-format +msgid "The URL %s does not point to a valid image." +msgstr "العنوان %s لا يحتوي على صورة صالحة." + +#: .\core\validators.py:166 +#, python-format +msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid." +msgstr "رقم الهاتف يجب أن يكون بتنسيق XXX-XXX-XXXX. \"%s\" غير صالح." + +#: .\core\validators.py:174 +#, python-format +msgid "The URL %s does not point to a valid QuickTime video." +msgstr "هذا العنوان %s لا يشير إلى مقطع فيديو QuickTime صالح." + +#: .\core\validators.py:178 +msgid "A valid URL is required." +msgstr "يجب ادخال عنوان صالح." + +#: .\core\validators.py:192 +#, python-format +msgid "" +"Valid HTML is required. Specific errors are:\n" +"%s" +msgstr "" +"مطلوب شفرة HTML صالحة، الأخطاء على وجه التحديد هي:\n" +"%s" + +#: .\core\validators.py:199 +#, python-format +msgid "Badly formed XML: %s" +msgstr "XML مهيئة بصورة سيئة: %s" + +#: .\core\validators.py:209 +#, python-format +msgid "Invalid URL: %s" +msgstr "وصلة غير صالحة: %s" + +#: .\core\validators.py:213 +#: .\core\validators.py:215 +#, python-format +msgid "The URL %s is a broken link." +msgstr "الوصلة %s غير صحيحة." + +#: .\core\validators.py:221 +msgid "Enter a valid U.S. state abbreviation." +msgstr "أدخل اختصار ولاية أمريكية صحيحا." + +#: .\core\validators.py:236 +#, python-format +msgid "Watch your mouth! The word %s is not allowed here." +msgid_plural "Watch your mouth! The words %s are not allowed here." +msgstr[0] "انته إلى ما تقول! الكلمة %s غير مسموح بها هنا." +msgstr[1] "انتبه إلى ما تقول! الكلمتان %s غير مسموح بهما هنا." +msgstr[2] "انتبه إلى ما تقول! الكلمات %s غير مسموح بها هنا." +msgstr[3] "انتبه إلى ما تقول! الكلمات %s غير مسموح بها هنا." + +#: .\core\validators.py:243 +#, python-format +msgid "This field must match the '%s' field." +msgstr "هذا الحقل يجب أن يطابق الحقل '%s'." + +#: .\core\validators.py:262 +msgid "Please enter something for at least one field." +msgstr "الرجاء ادخال شيء ما في حقل واحد على الأقل." + +#: .\core\validators.py:271 +#: .\core\validators.py:282 +msgid "Please enter both fields or leave them both empty." +msgstr "الرجاء ادخال كلا الحقلين أن ترك كلاهما فارغا." + +#: .\core\validators.py:289 +#, python-format +msgid "This field must be given if %(field)s is %(value)s" +msgstr "هذا الحقل يجب أن يعطي إذا كان %(field)s %(value)s" + +#: .\core\validators.py:301 +#, python-format +msgid "This field must be given if %(field)s is not %(value)s" +msgstr "هذا الحقل يجب أن يعطى إذا لم يكن %(field)s %(value)s" + +#: .\core\validators.py:320 +msgid "Duplicate values are not allowed." +msgstr "القيم المكررة غير مسموح بها." + +#: .\core\validators.py:343 +#, python-format +msgid "This value must be a power of %s." +msgstr "يجب أن تكون القيام من مضاعفات %s." + +#: .\core\validators.py:354 +msgid "Please enter a valid decimal number." +msgstr "الرجاء ادخال رقم عشري صالح." + +#: .\core\validators.py:356 +#, python-format +msgid "Please enter a valid decimal number with at most %s total digit." +msgid_plural "Please enter a valid decimal number with at most %s total digits." +msgstr[0] "رجاء أدخل رقم عشري صالح مكون من خانة واحدة على الأكثر." +msgstr[1] "رجاء أدخل رقم عشري صالح مكون من خانتين على الأكثر." +msgstr[2] "رجاء أدخل رقم عشري صالح مكون من %s خانات على الأكثر." +msgstr[3] "رجاء أدخل رقم عشري صالح مكون من %s خانة على الأكثر." + +#: .\core\validators.py:359 +#, python-format +msgid "Please enter a valid decimal number with a whole part of at most %s digit." +msgid_plural "Please enter a valid decimal number with a whole part of at most %s digits." +msgstr[0] "رجاء أدخل رقم عشري صالح يكون الجزء الصحيح منه مكونا من خانة واحدة على الأكثر." +msgstr[1] "رجاء أدخل رقم عشري صالح يكون الجزء الصحيح منه مكونا من خانتين على الأكثر." +msgstr[2] "رجاء أدخل رقم عشري صالح يكون الجزء الصحيح منه مكونا من %s خانات على الأكثر." +msgstr[3] "رجاء أدخل رقم عشري صالح يكون الجزء الصحيح منه مكونا من %s خانة على الأكثر." + +#: .\core\validators.py:362 +#, python-format +msgid "Please enter a valid decimal number with at most %s decimal place." +msgid_plural "Please enter a valid decimal number with at most %s decimal places." +msgstr[0] "الرجاء ادخال رقم عشري صالح تكون فيه خانة عشرية واحدة على الأكثر." +msgstr[1] "الرجاء ادخال رقم عشري صالح تكون فيه خانتان عشريتان على الأكثر." +msgstr[2] "الرجاء ادخال رقم عشري صالح تكون فيه %s خانات عشرية على الأكثر." +msgstr[3] "الرجاء ادخال رقم عشري صالح تكون فيه %s خانة عشرية على الأكثر." + +#: .\core\validators.py:372 +#, python-format +msgid "Make sure your uploaded file is at least %s bytes big." +msgstr "تأكد من أن حجم الملف الذي قمت برفعه لا يقل عن %s بايت." + +#: .\core\validators.py:373 +#, python-format +msgid "Make sure your uploaded file is at most %s bytes big." +msgstr "تأكد من أن الملف الذي قمت برفعه لا يزيد عن %s بايت." + +#: .\core\validators.py:390 +msgid "The format for this field is wrong." +msgstr "تنسيق هذا الحقل خاطئ." + +#: .\core\validators.py:405 +msgid "This field is invalid." +msgstr "هذا الحقل غير صحيح." + +#: .\core\validators.py:441 +#, python-format +msgid "Could not retrieve anything from %s." +msgstr "تعذر جلب أي شيء من %s." + +#: .\core\validators.py:444 +#, python-format +msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." +msgstr "الوصلة %(url)s أعادت ترويسة Content-Type الخاطئة '%(contenttype)s'." + +#: .\core\validators.py:477 +#, python-format +msgid "Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with \"%(start)s\".)" +msgstr "الرجاء اغلاق الوسم %(tag)s في سطر %(line)s. (يبدأ السطر هكذا \"%(start)s\".)" + +#: .\core\validators.py:481 +#, python-format +msgid "Some text starting on line %(line)s is not allowed in that context. (Line starts with \"%(start)s\".)" +msgstr "بعض النص الذي يبدأ في سطر %(line)s غير مسموح به في هذا السياق. (يبدأ السطر هكذا \"%(start)s\".)" + +#: .\core\validators.py:486 +#, python-format +msgid "\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%(start)s\".)" +msgstr "\"%(attr)s\" في السطر %(line)s هي سمة غير صالحة. (يبدأ السطر هكذا \"%(start)s\".)" + +#: .\core\validators.py:491 +#, python-format +msgid "\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%(start)s\".)" +msgstr "\"<%(tag)s>\" في السطر %(line)s وسم غير صالح. (يبدأ السطر هكذا \"%(start)s\".)" + +#: .\core\validators.py:495 +#, python-format +msgid "A tag on line %(line)s is missing one or more required attributes. (Line starts with \"%(start)s\".)" +msgstr "هنالك وسم في السطر %(line)s تنقصه سمة واحدة أو أكثر. (يبدأ السطر هكذا \"%(start)s\".)" + +#: .\core\validators.py:500 +#, python-format +msgid "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line starts with \"%(start)s\".)" +msgstr "السمة \"%(attr)s\" في السطر %(line)s تمتلك قيمة غير صالحة. (يبدأ السطر هكذا \"%(start)s\".)" + +#: .\db\models\manipulators.py:302 +#, python-format +msgid "%(object)s with this %(type)s already exists for the given %(field)s." +msgstr "%(object)s مع هذا %(type)s موجودة بالفعل لأجل %(field)s." + +#: .\db\models\fields\related.py:51 +#, python-format +msgid "Please enter a valid %s." +msgstr "الرجاء ادخال %s صالح." + +#: .\db\models\fields\related.py:618 +msgid "Separate multiple IDs with commas." +msgstr "افصل بين المعرفات بفواصل comma." + +#: .\db\models\fields\related.py:620 +msgid "Hold down \"Control\", or \"Command\" on a Mac, to select more than one." +msgstr "اضغط زر التحكم \"Control\", أو \"Command\" على أجهزة Mac لاختيار أكثر من واحد." + +#: .\db\models\fields\related.py:664 +#, python-format +msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." +msgid_plural "Please enter valid %(self)s IDs. The values %(value)r are invalid." +msgstr[0] "الرجاء ادخال معرفات %(self)s صالحة، القيمة %(value)r غير صالحة." +msgstr[1] "الرجاء ادخال معرفات %(self)s صالحة، القيمتان %(value)r غير صالحة." +msgstr[2] "الرجاء ادخال معرفات %(self)s صالحة، القيم %(value)r غير صالحة." +msgstr[3] "الرجاء ادخال معرفات %(self)s صالحة، القيم %(value)r غير صالحة." + +#: .\db\models\fields\__init__.py:40 +#, python-format +msgid "%(optname)s with this %(fieldname)s already exists." +msgstr "%(optname)s بالحقل %(fieldname)s موجود بالفعل." + +#: .\db\models\fields\__init__.py:114 +#: .\db\models\fields\__init__.py:265 +#: .\db\models\fields\__init__.py:548 +#: .\db\models\fields\__init__.py:559 +#: .\forms\__init__.py:346 +msgid "This field is required." +msgstr "هذا الحقل مطلوب." + +#: .\db\models\fields\__init__.py:337 +msgid "This value must be an integer." +msgstr "هذه القيمة يجب أن تكون رقما صحيحا." + +#: .\db\models\fields\__init__.py:369 +msgid "This value must be either True or False." +msgstr "هذه القيمة يجب أن تكون إما صح أو خطأ." + +#: .\db\models\fields\__init__.py:385 +msgid "This field cannot be null." +msgstr "لا يمكن أن تكون قيمة هذا الحقل لا شيء." + +#: .\db\models\fields\__init__.py:568 +msgid "Enter a valid filename." +msgstr "أدخل اسم ملف صالح." + +#: .\forms\__init__.py:381 +#, python-format +msgid "Ensure your text is less than %s character." +msgid_plural "Ensure your text is less than %s characters." +msgstr[0] "تأكد من أن النص الذي أدخلته أقل من خانة واحدة." +msgstr[1] "تأكد من أن النص الذي أدخلته أقل من خانتين." +msgstr[2] "تأكد من أن النص الذي أدخلته أقل من %s خانات." +msgstr[3] "تأكد من أن النص الذي أدخلته أقل من %s خانة." + +#: .\forms\__init__.py:386 +msgid "Line breaks are not allowed here." +msgstr "الأسطر الجديدة غير مسموح هتا." + +#: .\forms\__init__.py:485 +#: .\forms\__init__.py:558 +#: .\forms\__init__.py:597 +#, python-format +msgid "Select a valid choice; '%(data)s' is not in %(choices)s." +msgstr "حدد خيارا صحيحا; '%(data)s' ليست ضمن %(choices)s." + +#: .\forms\__init__.py:661 +msgid "The submitted file is empty." +msgstr "الملف الذي قمت بارساله فارغ." + +#: .\forms\__init__.py:717 +msgid "Enter a whole number between -32,768 and 32,767." +msgstr "أدخل رقما صحيحا بين -32,768 و 32,767." + +#: .\forms\__init__.py:727 +msgid "Enter a positive number." +msgstr "أدخل رقما موجبا." + +#: .\forms\__init__.py:737 +msgid "Enter a whole number between 0 and 32,767." +msgstr "أدخل رقما صحيحا بين 0 و 32,767." + +#: .\template\defaultfilters.py:401 +msgid "yes,no,maybe" +msgstr "نعم،لا،ربما" + +#: .\utils\dates.py:6 +msgid "Monday" +msgstr "الاثنين" + +#: .\utils\dates.py:6 +msgid "Tuesday" +msgstr "الثلاثاء" + +#: .\utils\dates.py:6 +msgid "Wednesday" +msgstr "الأربعاء" + +#: .\utils\dates.py:6 +msgid "Thursday" +msgstr "الخميس" + +#: .\utils\dates.py:6 +msgid "Friday" +msgstr "الجمعة" + +#: .\utils\dates.py:7 +msgid "Saturday" +msgstr "السبت" + +#: .\utils\dates.py:7 +msgid "Sunday" +msgstr "الأحد" + +#: .\utils\dates.py:14 +msgid "January" +msgstr "يناير" + +#: .\utils\dates.py:14 +msgid "February" +msgstr "فبراير" + +#: .\utils\dates.py:14 +#: .\utils\dates.py:27 +msgid "March" +msgstr "مارس" + +#: .\utils\dates.py:14 +#: .\utils\dates.py:27 +msgid "April" +msgstr "ابريل" + +#: .\utils\dates.py:14 +#: .\utils\dates.py:27 +msgid "May" +msgstr "مايو" + +#: .\utils\dates.py:14 +#: .\utils\dates.py:27 +msgid "June" +msgstr "يونيو" + +#: .\utils\dates.py:15 +#: .\utils\dates.py:27 +msgid "July" +msgstr "يوليو" + +#: .\utils\dates.py:15 +msgid "August" +msgstr "أغسطس" + +#: .\utils\dates.py:15 +msgid "September" +msgstr "سبتمبر" + +#: .\utils\dates.py:15 +msgid "October" +msgstr "أكتوبر" + +#: .\utils\dates.py:15 +msgid "November" +msgstr "نوفمبر" + +#: .\utils\dates.py:16 +msgid "December" +msgstr "ديسمبر" + +#: .\utils\dates.py:19 +msgid "jan" +msgstr "" + +#: .\utils\dates.py:19 +msgid "feb" +msgstr "" + +#: .\utils\dates.py:19 +msgid "mar" +msgstr "" + +#: .\utils\dates.py:19 +msgid "apr" +msgstr "" + +#: .\utils\dates.py:19 +msgid "may" +msgstr "" + +#: .\utils\dates.py:19 +msgid "jun" +msgstr "" + +#: .\utils\dates.py:20 +msgid "jul" +msgstr "" + +#: .\utils\dates.py:20 +msgid "aug" +msgstr "" + +#: .\utils\dates.py:20 +msgid "sep" +msgstr "" + +#: .\utils\dates.py:20 +msgid "oct" +msgstr "" + +#: .\utils\dates.py:20 +msgid "nov" +msgstr "" + +#: .\utils\dates.py:20 +msgid "dec" +msgstr "" + +#: utils/dates.py:27 +msgid "Jan." +msgstr "يناير" + +#: utils/dates.py:27 +msgid "Feb." +msgstr "فبراير" + +#: utils/dates.py:28 +msgid "Aug." +msgstr "أغسطس" + +#: utils/dates.py:28 +msgid "Sept." +msgstr "سبتمبر" + +#: utils/dates.py:28 +msgid "Oct." +msgstr "أكتوبر" + +#: utils/dates.py:28 +msgid "Nov." +msgstr "نوفمبر" + +#: utils/dates.py:28 +msgid "Dec." +msgstr "ديسمبر" + +#: .\utils\timesince.py:12 +msgid "year" +msgid_plural "years" +msgstr[0] "سنة" +msgstr[1] "سنتان" +msgstr[2] "سنوات" +msgstr[3] "سنة" + +#: .\utils\timesince.py:13 +msgid "month" +msgid_plural "months" +msgstr[0] "شهر" +msgstr[1] "شهران" +msgstr[2] "شهور" +msgstr[3] "شهر" + +#: .\utils\timesince.py:14 +msgid "week" +msgid_plural "weeks" +msgstr[0] "أسبوع" +msgstr[1] "أسبوعان" +msgstr[2] "أسابيع" +msgstr[3] "أسبوع" + +#: .\utils\timesince.py:15 +msgid "day" +msgid_plural "days" +msgstr[0] "يوم" +msgstr[1] "يومان" +msgstr[2] "أيام" +msgstr[3] "يوم" + +#: .\utils\timesince.py:16 +msgid "hour" +msgid_plural "hours" +msgstr[0] "ساعة" +msgstr[1] "ساعتان" +msgstr[2] "ساعات" +msgstr[3] "ساعة" + +#: .\utils\timesince.py:17 +msgid "minute" +msgid_plural "minutes" +msgstr[0] "دقيقة" +msgstr[1] "دقيقتان" +msgstr[2] "دقائق" +msgstr[3] "دقيقة" + +#: .\utils\translation.py:363 +msgid "DATE_FORMAT" +msgstr "" + +#: .\utils\translation.py:364 +msgid "DATETIME_FORMAT" +msgstr "" + +#: .\utils\translation.py:365 +msgid "TIME_FORMAT" +msgstr "" + +#: .\utils\translation.py:381 +msgid "YEAR_MONTH_FORMAT" +msgstr "" + +#: .\utils\translation.py:382 +msgid "MONTH_DAY_FORMAT" +msgstr "" + diff --git a/django/conf/locale/ar/LC_MESSAGES/djangojs.mo b/django/conf/locale/ar/LC_MESSAGES/djangojs.mo new file mode 100644 index 0000000000..02c1d67b58 Binary files /dev/null and b/django/conf/locale/ar/LC_MESSAGES/djangojs.mo differ diff --git a/django/conf/locale/ar/LC_MESSAGES/djangojs.po b/django/conf/locale/ar/LC_MESSAGES/djangojs.po new file mode 100644 index 0000000000..29b16aef26 --- /dev/null +++ b/django/conf/locale/ar/LC_MESSAGES/djangojs.po @@ -0,0 +1,110 @@ +# 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 , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Django SVN\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2005-12-09 11:51+0100\n" +"PO-Revision-Date: 2006-07-06 23:50+0300\n" +"Last-Translator: Ahmad Alhashemi \n" +"Language-Team: Ahmad Alhashemi \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Arabic\n" +"X-Poedit-Country: Kuwait\n" +"X-Poedit-SourceCharset: utf-8\n" + +#: contrib/admin/media/js/SelectFilter2.js:33 +#, perl-format +msgid "Available %s" +msgstr "%s متوفرة" + +#: contrib/admin/media/js/SelectFilter2.js:41 +msgid "Choose all" +msgstr "اختيار الكل" + +#: contrib/admin/media/js/SelectFilter2.js:46 +msgid "Add" +msgstr "إضافة" + +#: contrib/admin/media/js/SelectFilter2.js:48 +msgid "Remove" +msgstr "حذف" + +#: contrib/admin/media/js/SelectFilter2.js:53 +#, perl-format +msgid "Chosen %s" +msgstr "%s اختيرت" + +#: contrib/admin/media/js/SelectFilter2.js:54 +msgid "Select your choice(s) and click " +msgstr "حدد خيارك أو خياراتك واضغط" + +#: contrib/admin/media/js/SelectFilter2.js:59 +msgid "Clear all" +msgstr "مسح الكل" + +#: contrib/admin/media/js/dateparse.js:26 +#: contrib/admin/media/js/calendar.js:24 +msgid "January February March April May June July August September October November December" +msgstr "يناير فبراير مارس إبريل مايو يونيو يوليو أغسطس سبتمبر أكتوبر نوفمبر ديسمبر" + +#: contrib/admin/media/js/dateparse.js:27 +msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday" +msgstr "الأحد الأثنين الثلاثاء الأربعاء الخميس الجمعة السبت" + +#: contrib/admin/media/js/calendar.js:25 +msgid "S M T W T F S" +msgstr "أ أ ث أ خ ج س" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45 +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80 +msgid "Now" +msgstr "الآن" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48 +msgid "Clock" +msgstr "الساعة" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77 +msgid "Choose a time" +msgstr "اختر وقتا ما" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81 +msgid "Midnight" +msgstr "منتصف الليل" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82 +msgid "6 a.m." +msgstr "6 ص." + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83 +msgid "Noon" +msgstr "الظهر" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87 +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168 +msgid "Cancel" +msgstr "الغاء" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111 +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162 +msgid "Today" +msgstr "اليوم" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114 +msgid "Calendar" +msgstr "التقويم" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160 +msgid "Yesterday" +msgstr "يوم أمس" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164 +msgid "Tomorrow" +msgstr "الغد" + diff --git a/django/conf/locale/zh_CN/LC_MESSAGES/djangojs.mo b/django/conf/locale/zh_CN/LC_MESSAGES/djangojs.mo new file mode 100644 index 0000000000..983a8a7154 Binary files /dev/null and b/django/conf/locale/zh_CN/LC_MESSAGES/djangojs.mo differ diff --git a/django/contrib/admin/templates/admin/base.html b/django/contrib/admin/templates/admin/base.html index 67fe27529c..114f98c369 100644 --- a/django/contrib/admin/templates/admin/base.html +++ b/django/contrib/admin/templates/admin/base.html @@ -26,7 +26,7 @@ {% block nav-global %}{% endblock %} - {% block breadcrumbs %}{% endblock %} + {% block breadcrumbs %}{% endblock %} {% endif %} {% if messages %} @@ -36,7 +36,7 @@
      {% block pretitle %}{% endblock %} - {% block content_title %}{% if title %}

      {{ title }}

      {% endif %}{% endblock %} + {% block content_title %}{% if title %}

      {{ title|escape }}

      {% endif %}{% endblock %} {% block content %}{{ content }}{% endblock %} {% block sidebar %}{% endblock %}
      diff --git a/django/contrib/admin/templates/admin/base_site.html b/django/contrib/admin/templates/admin/base_site.html index b867bd29bd..2bc7310873 100644 --- a/django/contrib/admin/templates/admin/base_site.html +++ b/django/contrib/admin/templates/admin/base_site.html @@ -1,7 +1,7 @@ {% extends "admin/base.html" %} {% load i18n %} -{% block title %}{{ title }} | {% trans 'Django site admin' %}{% endblock %} +{% block title %}{{ title|escape }} | {% trans 'Django site admin' %}{% endblock %} {% block branding %}

      {% trans 'Django administration' %}

      diff --git a/django/contrib/admin/templates/admin/change_form.html b/django/contrib/admin/templates/admin/change_form.html index fa04969f01..e61eb5513b 100644 --- a/django/contrib/admin/templates/admin/change_form.html +++ b/django/contrib/admin/templates/admin/change_form.html @@ -11,8 +11,8 @@ {% block breadcrumbs %}{% if not is_popup %} {% endif %}{% endblock %} {% block content %}
      diff --git a/django/contrib/admin/templates/admin/change_list.html b/django/contrib/admin/templates/admin/change_list.html index 5b54bfb8cc..bd2304bd52 100644 --- a/django/contrib/admin/templates/admin/change_list.html +++ b/django/contrib/admin/templates/admin/change_list.html @@ -3,12 +3,12 @@ {% block stylesheet %}{% admin_media_prefix %}css/changelists.css{% endblock %} {% block bodyclass %}change-list{% endblock %} {% block userlinks %}{% trans 'Documentation' %} / {% trans 'Change password' %} / {% trans 'Log out' %}{% endblock %} -{% if not is_popup %}{% block breadcrumbs %}{% endblock %}{% endif %} +{% if not is_popup %}{% block breadcrumbs %}{% endblock %}{% endif %} {% block coltype %}flex{% endblock %} {% block content %}
      {% if has_add_permission %} - + {% endif %}
      {% block search %}{% search_form cl %}{% endblock %} diff --git a/django/contrib/admin/templates/admin/date_hierarchy.html b/django/contrib/admin/templates/admin/date_hierarchy.html index a53d810f93..d2d69616c7 100644 --- a/django/contrib/admin/templates/admin/date_hierarchy.html +++ b/django/contrib/admin/templates/admin/date_hierarchy.html @@ -1,10 +1,10 @@ {% if show %}

      -{% endif %} \ No newline at end of file +{% endif %} diff --git a/django/contrib/admin/templates/admin/delete_confirmation.html b/django/contrib/admin/templates/admin/delete_confirmation.html index f907c18a16..3921ab69e3 100644 --- a/django/contrib/admin/templates/admin/delete_confirmation.html +++ b/django/contrib/admin/templates/admin/delete_confirmation.html @@ -4,21 +4,21 @@ {% block breadcrumbs %} {% endblock %} {% block content %} {% if perms_lacking %} -

      {% blocktrans %}Deleting the {{ object_name }} '{{ object }}' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:{% endblocktrans %}

      +

      {% blocktrans with object|escape as escaped_object %}Deleting the {{ object_name }} '{{ escaped_object }}' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:{% endblocktrans %}

        {% for obj in perms_lacking %} -
      • {{ obj }}
      • +
      • {{ obj|escape }}
      • {% endfor %}
      {% else %} -

      {% blocktrans %}Are you sure you want to delete the {{ object_name }} "{{ object }}"? All of the following related items will be deleted:{% endblocktrans %}

      +

      {% blocktrans with object|escape as escaped_object %}Are you sure you want to delete the {{ object_name }} "{{ escaped_object }}"? All of the following related items will be deleted:{% endblocktrans %}

        {{ deleted_objects|unordered_list }}
      diff --git a/django/contrib/admin/templates/admin/edit_inline_stacked.html b/django/contrib/admin/templates/admin/edit_inline_stacked.html index 45aa0a4f58..48ecc698d9 100644 --- a/django/contrib/admin/templates/admin/edit_inline_stacked.html +++ b/django/contrib/admin/templates/admin/edit_inline_stacked.html @@ -1,7 +1,7 @@ {% load admin_modify %}
      {% for fcw in bound_related_object.form_field_collection_wrappers %} -

      {{ bound_related_object.relation.opts.verbose_name|capfirst }} #{{ forloop.counter }}

      +

      {{ bound_related_object.relation.opts.verbose_name|capfirst|escape }} #{{ forloop.counter }}

      {% if bound_related_object.show_url %}{% if fcw.obj.original %}

      View on site

      {% endif %}{% endif %} diff --git a/django/contrib/admin/templates/admin/edit_inline_tabular.html b/django/contrib/admin/templates/admin/edit_inline_tabular.html index e9535df02c..13d528331b 100644 --- a/django/contrib/admin/templates/admin/edit_inline_tabular.html +++ b/django/contrib/admin/templates/admin/edit_inline_tabular.html @@ -1,10 +1,10 @@ {% load admin_modify %}
      -

      {{ bound_related_object.relation.opts.verbose_name_plural|capfirst }}

      +

      {{ bound_related_object.relation.opts.verbose_name_plural|capfirst|escape }}

      {% for fw in bound_related_object.field_wrapper_list %} {% if fw.needs_header %} - {{ fw.field.verbose_name|capfirst }} + {{ fw.field.verbose_name|capfirst|escape }} {% endif %} {% endfor %} {% for fcw in bound_related_object.form_field_collection_wrappers %} diff --git a/django/contrib/admin/templates/admin/filter.html b/django/contrib/admin/templates/admin/filter.html index 5b0e78b6fc..8b5b521437 100644 --- a/django/contrib/admin/templates/admin/filter.html +++ b/django/contrib/admin/templates/admin/filter.html @@ -1,5 +1,5 @@ {% load i18n %} -

      {% blocktrans %} By {{ title }} {% endblocktrans %}

      +

      {% blocktrans with title|escape as filter_title %} By {{ filter_title }} {% endblocktrans %}

        {% for choice in choices %} diff --git a/django/contrib/admin/templates/admin/index.html b/django/contrib/admin/templates/admin/index.html index f7b121723a..aa63c14fce 100644 --- a/django/contrib/admin/templates/admin/index.html +++ b/django/contrib/admin/templates/admin/index.html @@ -19,9 +19,9 @@ {% for model in app.models %}
      {% if model.perms.change %} - + {% else %} - + {% endif %} {% if model.perms.add %} @@ -58,7 +58,7 @@ {% else %} {% endif %} diff --git a/django/contrib/admin/templates/admin/invalid_setup.html b/django/contrib/admin/templates/admin/invalid_setup.html index 1fa0d32358..1d7d61f0d2 100644 --- a/django/contrib/admin/templates/admin/invalid_setup.html +++ b/django/contrib/admin/templates/admin/invalid_setup.html @@ -1,7 +1,7 @@ {% extends "admin/base_site.html" %} {% load i18n %} -{% block breadcrumbs %}{% endblock %} +{% block breadcrumbs %}{% endblock %} {% block content %} diff --git a/django/contrib/admin/templates/admin/object_history.html b/django/contrib/admin/templates/admin/object_history.html index fc568305ca..14a77b8a31 100644 --- a/django/contrib/admin/templates/admin/object_history.html +++ b/django/contrib/admin/templates/admin/object_history.html @@ -2,7 +2,7 @@ {% load i18n %} {% block userlinks %}{% trans 'Documentation' %} / {% trans 'Change password' %} / {% trans 'Log out' %}{% endblock %} {% block breadcrumbs %} - + {% endblock %} {% block content %} diff --git a/django/contrib/admin/templates/admin/pagination.html b/django/contrib/admin/templates/admin/pagination.html index 7694e4c5b0..e1c09b2932 100644 --- a/django/contrib/admin/templates/admin/pagination.html +++ b/django/contrib/admin/templates/admin/pagination.html @@ -6,6 +6,6 @@ {% paginator_number cl i %} {% endfor %} {% endif %} -{{ cl.result_count }} {% ifequal cl.result_count 1 %}{{ cl.opts.verbose_name }}{% else %}{{ cl.opts.verbose_name_plural }}{% endifequal %} +{{ cl.result_count }} {% ifequal cl.result_count 1 %}{{ cl.opts.verbose_name|escape }}{% else %}{{ cl.opts.verbose_name_plural|escape }}{% endifequal %} {% if show_all_url %}  {% trans 'Show all' %}{% endif %}

      diff --git a/django/contrib/admin/templates/admin_doc/model_detail.html b/django/contrib/admin/templates/admin_doc/model_detail.html index 9ac56864fa..44fc43e704 100644 --- a/django/contrib/admin/templates/admin_doc/model_detail.html +++ b/django/contrib/admin/templates/admin_doc/model_detail.html @@ -9,13 +9,13 @@ {% endblock %} -{% block breadcrumbs %}{% endblock %} +{% block breadcrumbs %}{% endblock %} -{% block title %}Model: {{ name }}{% endblock %} +{% block title %}Model: {{ name|escape }}{% endblock %} {% block content %}
      -

      {{ summary }}

      +

      {{ summary|escape }}

      {% if description %}

      {% filter escape|linebreaksbr %}{% trans description %}{% endfilter %}

      @@ -35,7 +35,7 @@
      - + {% endfor %} diff --git a/django/contrib/admin/templates/admin_doc/template_detail.html b/django/contrib/admin/templates/admin_doc/template_detail.html index df67f1856b..280ea912d0 100644 --- a/django/contrib/admin/templates/admin_doc/template_detail.html +++ b/django/contrib/admin/templates/admin_doc/template_detail.html @@ -1,19 +1,19 @@ {% extends "admin/base_site.html" %} {% load i18n %} -{% block breadcrumbs %}{% endblock %} +{% block breadcrumbs %}{% endblock %} {% block userlinks %}{% trans 'Change password' %} / {% trans 'Log out' %}{% endblock %} -{% block title %}Template: {{ name }}{% endblock %} +{% block title %}Template: {{ name|escape }}{% endblock %} {% block content %} -

      Template: "{{ name }}"

      +

      Template: "{{ name|escape }}"

      {% regroup templates|dictsort:"site_id" by site as templates_by_site %} {% for group in templates_by_site %} -

      Search path for template "{{ name }}" on {{ group.grouper }}:

      +

      Search path for template "{{ name|escape }}" on {{ group.grouper }}:

        {% for template in group.list|dictsort:"order" %} -
      1. {{ template.file }}{% if not template.exists %} (does not exist){% endif %}
      2. +
      3. {{ template.file|escape }}{% if not template.exists %} (does not exist){% endif %}
      4. {% endfor %}
      {% endfor %} diff --git a/django/contrib/admin/templates/admin_doc/view_detail.html b/django/contrib/admin/templates/admin_doc/view_detail.html index ba90399358..ed90657361 100644 --- a/django/contrib/admin/templates/admin_doc/view_detail.html +++ b/django/contrib/admin/templates/admin_doc/view_detail.html @@ -8,7 +8,7 @@

      {{ name }}

      -

      {{ summary }}

      +

      {{ summary|escape }}

      {{ body }}

      diff --git a/django/contrib/admin/templates/widget/file.html b/django/contrib/admin/templates/widget/file.html index e4a0756211..e584abf956 100644 --- a/django/contrib/admin/templates/widget/file.html +++ b/django/contrib/admin/templates/widget/file.html @@ -1,4 +1,4 @@ {% load admin_modify i18n %}{% if bound_field.original_value %} -{% trans "Currently:" %} {{ bound_field.original_value }}
      +{% trans "Currently:" %} {{ bound_field.original_value|escape }}
      {% trans "Change:" %}{% output_all bound_field.form_fields %} {% else %} {% output_all bound_field.form_fields %} {% endif %} diff --git a/django/contrib/admin/templates/widget/foreign.html b/django/contrib/admin/templates/widget/foreign.html index 6b43d044bd..301f5214db 100644 --- a/django/contrib/admin/templates/widget/foreign.html +++ b/django/contrib/admin/templates/widget/foreign.html @@ -15,6 +15,6 @@ {{ bound_field.original_value }} {% endif %} {% if bound_field.raw_id_admin %} - {% if bound_field.existing_display %} {{ bound_field.existing_display|truncatewords:"14" }}{% endif %} + {% if bound_field.existing_display %} {{ bound_field.existing_display|truncatewords:"14"|escape }}{% endif %} {% endif %} {% endif %} diff --git a/django/contrib/admin/templates/widget/one_to_one.html b/django/contrib/admin/templates/widget/one_to_one.html index a79a12314f..efd0117bf2 100644 --- a/django/contrib/admin/templates/widget/one_to_one.html +++ b/django/contrib/admin/templates/widget/one_to_one.html @@ -1,2 +1,2 @@ {% if add %}{% include "widget/foreign.html" %}{% endif %} -{% if change %}{% if bound_field.existing_display %} {{ bound_field.existing_display|truncatewords:"14" }}{% endif %}{% endif %} +{% if change %}{% if bound_field.existing_display %} {{ bound_field.existing_display|truncatewords:"14"|escape }}{% endif %}{% endif %} diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py index 0e550dd471..ca250ba433 100644 --- a/django/contrib/admin/templatetags/admin_list.py +++ b/django/contrib/admin/templatetags/admin_list.py @@ -165,12 +165,14 @@ def items_for_result(cl, result): result_repr = escape(str(field_val)) if result_repr == '': result_repr = ' ' - if first: # First column is a special case + # If list_display_links not defined, add the link tag to the first field + if (first and not cl.lookup_opts.admin.list_display_links) or field_name in cl.lookup_opts.admin.list_display_links: + table_tag = {True:'th', False:'td'}[first] first = False url = cl.url_for_result(result) result_id = str(getattr(result, pk)) # str() is needed in case of 23L (long ints) - yield ('%s' % \ - (row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %r); return false;"' % result_id or ''), result_repr)) + yield ('<%s%s>%s' % \ + (table_tag, row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %r); return false;"' % result_id or ''), result_repr, table_tag)) else: yield ('%s' % (row_class, result_repr)) diff --git a/django/contrib/auth/__init__.py b/django/contrib/auth/__init__.py index 2150893022..1c821801ef 100644 --- a/django/contrib/auth/__init__.py +++ b/django/contrib/auth/__init__.py @@ -38,7 +38,7 @@ def authenticate(**credentials): if user is None: continue # Annotate the user object with the path of the backend. - user.backend = str(backend.__class__) + user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) return user def login(request, user): diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py index e37f5a4497..cca3c62252 100644 --- a/django/contrib/auth/models.py +++ b/django/contrib/auth/models.py @@ -239,7 +239,7 @@ class User(models.Model): app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.') model = models.get_model(app_label, model_name) self._profile_cache = model._default_manager.get(user__id__exact=self.id) - except ImportError, ImproperlyConfigured: + except (ImportError, ImproperlyConfigured): raise SiteProfileNotAvailable return self._profile_cache diff --git a/django/contrib/flatpages/models.py b/django/contrib/flatpages/models.py index 733706257c..bc2a392121 100644 --- a/django/contrib/flatpages/models.py +++ b/django/contrib/flatpages/models.py @@ -10,7 +10,7 @@ class FlatPage(models.Model): content = models.TextField(_('content')) enable_comments = models.BooleanField(_('enable comments')) template_name = models.CharField(_('template name'), maxlength=70, blank=True, - help_text=_("Example: 'flatpages/contact_page'. If this isn't provided, the system will use 'flatpages/default'.")) + help_text=_("Example: 'flatpages/contact_page.html'. If this isn't provided, the system will use 'flatpages/default.html'.")) registration_required = models.BooleanField(_('registration required'), help_text=_("If this is checked, only logged-in users will be able to view the page.")) sites = models.ManyToManyField(Site) class Meta: diff --git a/django/core/management.py b/django/core/management.py index fec60ecd08..59f1fed290 100644 --- a/django/core/management.py +++ b/django/core/management.py @@ -45,8 +45,8 @@ def disable_termcolors(): global style style = dummy() -# Disable terminal coloring on Windows or if somebody's piping the output. -if sys.platform == 'win32' or not sys.stdout.isatty(): +# Disable terminal coloring on Windows, Pocket PC, or if somebody's piping the output. +if sys.platform == 'win32' or sys.platform == 'Pocket PC' or not sys.stdout.isatty(): disable_termcolors() # singleton representing the default connection @@ -847,6 +847,19 @@ def get_validation_errors(outfile, app=None): else: if isinstance(f, models.ManyToManyField): e.add(opts, '"admin.list_display" doesn\'t support ManyToManyFields (%r).' % fn) + # list_display_links + if opts.admin.list_display_links and not opts.admin.list_display: + e.add(opts, '"admin.list_display" must be defined for "admin.list_display_links" to be used.') + if not isinstance(opts.admin.list_display_links, (list, tuple)): + e.add(opts, '"admin.list_display_links", if given, must be set to a list or tuple.') + else: + for fn in opts.admin.list_display_links: + try: + f = opts.get_field(fn) + except models.FieldDoesNotExist: + e.add(opts, '"admin.list_filter" refers to %r, which isn\'t a field.' % fn) + if fn not in opts.admin.list_display: + e.add(opts, '"admin.list_display_links" refers to %r, which is not defined in "admin.list_display".' % fn) # list_filter if not isinstance(opts.admin.list_filter, (list, tuple)): e.add(opts, '"admin.list_filter", if given, must be set to a list or tuple.') @@ -922,7 +935,7 @@ def _check_for_validation_errors(app=None): sys.stderr.write(s.read()) sys.exit(1) -def runserver(addr, port): +def runserver(addr, port, use_reloader=True): "Starts a lightweight Web server for development." from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException from django.core.handlers.wsgi import WSGIHandler @@ -956,9 +969,12 @@ def runserver(addr, port): sys.exit(1) except KeyboardInterrupt: sys.exit(0) - from django.utils import autoreload - autoreload.main(inner_run) -runserver.args = '[optional port number, or ipaddr:port]' + if use_reloader: + from django.utils import autoreload + autoreload.main(inner_run) + else: + inner_run() +runserver.args = '[--noreload] [optional port number, or ipaddr:port]' def createcachetable(tablename): "Creates the table needed to use the SQL cache backend" @@ -1107,6 +1123,8 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None): help='Lets you manually add a directory the Python path, e.g. "/home/djangoprojects/myproject".') parser.add_option('--plain', action='store_true', dest='plain', help='Tells Django to use plain Python, not IPython, for "shell" command.') + parser.add_option('--noreload', action='store_false', dest='use_reloader', default=True, + help='Tells Django to NOT use the auto-reloader when running the development server.') options, args = parser.parse_args(argv[1:]) # Take care of options. @@ -1162,7 +1180,7 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None): addr, port = args[1].split(':') except ValueError: addr, port = '', args[1] - action_mapping[action](addr, port) + action_mapping[action](addr, port, options.use_reloader) elif action == 'runfcgi': action_mapping[action](args[1:]) else: diff --git a/django/core/validators.py b/django/core/validators.py index f98589578e..81bea23e36 100644 --- a/django/core/validators.py +++ b/django/core/validators.py @@ -23,7 +23,7 @@ ansi_datetime_re = re.compile('^%s %s$' % (_datere, _timere)) email_re = re.compile( r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string - r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$', re.IGNORECASE) # domain + r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE) # domain integer_re = re.compile(r'^-?\d+$') ip4_re = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$') phone_re = re.compile(r'^[A-PR-Y0-9]{3}-[A-PR-Y0-9]{3}-[A-PR-Y0-9]{4}$', re.IGNORECASE) diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index 4c4b4a93c6..e74aa7e3c2 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -23,7 +23,7 @@ def add_lookup(rel_cls, field): name = field.rel.to module = rel_cls.__module__ key = (module, name) - # Has the model already been loaded? + # Has the model already been loaded? # If so, resolve the string reference right away model = get_model(rel_cls._meta.app_label,field.rel.to) if model: @@ -46,7 +46,7 @@ def manipulator_valid_rel_key(f, self, field_data, all_data): "Validates that the value is a valid foreign key" klass = f.rel.to try: - klass._default_manager.get(pk=field_data) + klass._default_manager.get(**{f.rel.field_name: field_data}) except klass.DoesNotExist: raise validators.ValidationError, _("Please enter a valid %s.") % f.verbose_name @@ -79,11 +79,11 @@ class RelatedField(object): self.contribute_to_related_class(other, related) def get_db_prep_lookup(self, lookup_type, value): - # If we are doing a lookup on a Related Field, we must be - # comparing object instances. The value should be the PK of value, + # If we are doing a lookup on a Related Field, we must be + # comparing object instances. The value should be the PK of value, # not value itself. def pk_trace(value): - # Value may be a primary key, or an object held in a relation. + # Value may be a primary key, or an object held in a relation. # If it is an object, then we need to get the primary key value for # that object. In certain conditions (especially one-to-one relations), # the primary key may itself be an object - so we need to keep drilling @@ -94,8 +94,8 @@ class RelatedField(object): v = getattr(v, v._meta.pk.name) except AttributeError: pass - return v - + return v + if lookup_type == 'exact': return [pk_trace(value)] if lookup_type == 'in': @@ -103,7 +103,7 @@ class RelatedField(object): elif lookup_type == 'isnull': return [] raise TypeError, "Related Field has invalid lookup: %s" % lookup_type - + def _get_related_query_name(self, opts): # This method defines the name that can be used to identify this related object # in a table-spanning query. It uses the lower-cased object_name by default, diff --git a/django/db/models/options.py b/django/db/models/options.py index 818bb62441..7732979c56 100644 --- a/django/db/models/options.py +++ b/django/db/models/options.py @@ -212,12 +212,13 @@ class Options(object): return self._field_types[field_type] class AdminOptions(object): - def __init__(self, fields=None, js=None, list_display=None, list_filter=None, + def __init__(self, fields=None, js=None, list_display=None, list_display_links=None, list_filter=None, date_hierarchy=None, save_as=False, ordering=None, search_fields=None, save_on_top=False, list_select_related=False, manager=None, list_per_page=100): self.fields = fields self.js = js or [] self.list_display = list_display or ['__str__'] + self.list_display_links = list_display_links or [] self.list_filter = list_filter or [] self.date_hierarchy = date_hierarchy self.save_as, self.ordering = save_as, ordering diff --git a/django/db/models/query.py b/django/db/models/query.py index 73275d66a4..1f3fc474c7 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -85,8 +85,8 @@ class QuerySet(object): self._where = [] # List of extra WHERE clauses to use. self._params = [] # List of params to use for extra WHERE clauses. self._tables = [] # List of extra tables to use. - self._offset = None # OFFSET clause - self._limit = None # LIMIT clause + self._offset = None # OFFSET clause. + self._limit = None # LIMIT clause. self._result_cache = None ######################## @@ -444,8 +444,7 @@ class QuerySet(object): params = self._params[:] # Convert self._filters into SQL. - tables2, joins2, where2, params2 = self._filters.get_sql(opts) - tables.extend(tables2) + joins2, where2, params2 = self._filters.get_sql(opts) joins.update(joins2) where.extend(where2) params.extend(params2) @@ -580,16 +579,15 @@ class QOperator(object): self.args = args def get_sql(self, opts): - tables, joins, where, params = [], SortedDict(), [], [] + joins, where, params = SortedDict(), [], [] for val in self.args: - tables2, joins2, where2, params2 = val.get_sql(opts) - tables.extend(tables2) + joins2, where2, params2 = val.get_sql(opts) joins.update(joins2) where.extend(where2) params.extend(params2) if where: - return tables, joins, ['(%s)' % self.operator.join(where)], params - return tables, joins, [], params + return joins, ['(%s)' % self.operator.join(where)], params + return joins, [], params class QAnd(QOperator): "Encapsulates a combined query that uses 'AND'." @@ -640,9 +638,9 @@ class QNot(Q): self.q = q def get_sql(self, opts): - tables, joins, where, params = self.q.get_sql(opts) + joins, where, params = self.q.get_sql(opts) where2 = ['(NOT (%s))' % " AND ".join(where)] - return tables, joins, where2, params + return joins, where2, params def get_where_clause(opts, lookup_type, table_prefix, field_name, value): backend = opts.connection_info.backend @@ -682,20 +680,20 @@ def fill_table_cache(opts, select, tables, where, old_prefix, cache_tables_seen) place) for select_related queries. """ backend = opts.connection_info.backend + qn = backend.quote_name for f in opts.fields: if f.rel and not f.null: db_table = f.rel.to._meta.db_table if db_table not in cache_tables_seen: - tables.append(backend.quote_name(db_table)) + tables.append(qn(db_table)) else: # The table was already seen, so give it a table alias. new_prefix = '%s%s' % (db_table, len(cache_tables_seen)) - tables.append('%s %s' % (backend.quote_name(db_table), backend.quote_name(new_prefix))) + tables.append('%s %s' % (qn(db_table), qn(new_prefix))) db_table = new_prefix cache_tables_seen.append(db_table) where.append('%s.%s = %s.%s' % \ - (backend.quote_name(old_prefix), backend.quote_name(f.column), - backend.quote_name(db_table), backend.quote_name(f.rel.get_related_field().column))) - select.extend(['%s.%s' % (backend.quote_name(db_table), backend.quote_name(f2.column)) for f2 in f.rel.to._meta.fields]) + (qn(old_prefix), qn(f.column), qn(db_table), qn(f.rel.get_related_field().column))) + select.extend(['%s.%s' % (qn(db_table), qn(f2.column)) for f2 in f.rel.to._meta.fields]) fill_table_cache(f.rel.to._meta, select, tables, where, db_table, cache_tables_seen) def parse_lookup(kwarg_items, opts): @@ -719,39 +717,38 @@ def parse_lookup(kwarg_items, opts): # At present, this method only every returns INNER JOINs; the option is # there for others to implement custom Q()s, etc that return other join # types. - tables, joins, where, params = [], SortedDict(), [], [] + joins, where, params = SortedDict(), [], [] for kwarg, value in kwarg_items: if value is not None: path = kwarg.split(LOOKUP_SEPARATOR) # Extract the last elements of the kwarg. - # The very-last is the clause (equals, like, etc). - # The second-last is the table column on which the clause is + # The very-last is the lookup_type (equals, like, etc). + # The second-last is the table column on which the lookup_type is # to be performed. # The exceptions to this are: # 1) "pk", which is an implicit id__exact; - # if we find "pk", make the clause "exact', and insert + # if we find "pk", make the lookup_type "exact', and insert # a dummy name of None, which we will replace when # we know which table column to grab as the primary key. # 2) If there is only one part, or the last part is not a query # term, assume that the query is an __exact - clause = path.pop() - if clause == 'pk': - clause = 'exact' + lookup_type = path.pop() + if lookup_type == 'pk': + lookup_type = 'exact' path.append(None) - elif len(path) == 0 or clause not in QUERY_TERMS: - path.append(clause) - clause = 'exact' + elif len(path) == 0 or lookup_type not in QUERY_TERMS: + path.append(lookup_type) + lookup_type = 'exact' if len(path) < 1: raise TypeError, "Cannot parse keyword query %r" % kwarg - tables2, joins2, where2, params2 = lookup_inner(path, clause, value, opts, opts.db_table, None) - tables.extend(tables2) + joins2, where2, params2 = lookup_inner(path, lookup_type, value, opts, opts.db_table, None) joins.update(joins2) where.extend(where2) params.extend(params2) - return tables, joins, where, params + return joins, where, params class FieldFound(Exception): "Exception used to short circuit field-finding operations." @@ -770,8 +767,8 @@ def find_field(name, field_list, related_query): return None return matches[0] -def lookup_inner(path, clause, value, opts, table, column): - tables, joins, where, params = [], SortedDict(), [], [] +def lookup_inner(path, lookup_type, value, opts, table, column): + joins, where, params = SortedDict(), [], [] current_opts = opts current_table = table current_column = column @@ -780,6 +777,7 @@ def lookup_inner(path, clause, value, opts, table, column): info = current_opts.connection_info backend = info.backend connection = info.connection + qn = backend.quote_name name = path.pop(0) # Has the primary key been requested? If so, expand it out @@ -792,7 +790,7 @@ def lookup_inner(path, clause, value, opts, table, column): # Does the name belong to a defined many-to-many field? field = find_field(name, current_opts.many_to_many, False) if field: - new_table = current_table + LOOKUP_SEPARATOR + name + new_table = current_table + '__' + name new_opts = field.rel.to._meta new_column = new_opts.pk.column @@ -809,7 +807,7 @@ def lookup_inner(path, clause, value, opts, table, column): # Does the name belong to a reverse defined many-to-many field? field = find_field(name, current_opts.get_all_related_many_to_many_objects(), True) if field: - new_table = current_table + LOOKUP_SEPARATOR + name + new_table = current_table + '__' + name new_opts = field.opts new_column = new_opts.pk.column @@ -826,7 +824,7 @@ def lookup_inner(path, clause, value, opts, table, column): # Does the name belong to a one-to-many field? field = find_field(name, current_opts.get_all_related_objects(), True) if field: - new_table = table + LOOKUP_SEPARATOR + name + new_table = table + '__' + name new_opts = field.opts new_column = field.field.column join_column = opts.pk.column @@ -840,7 +838,7 @@ def lookup_inner(path, clause, value, opts, table, column): field = find_field(name, current_opts.fields, False) if field: if field.rel: # One-to-One/Many-to-one field - new_table = current_table + LOOKUP_SEPARATOR + name + new_table = current_table + '__' + name new_opts = field.rel.to._meta new_column = new_opts.pk.column join_column = field.column @@ -849,54 +847,41 @@ def lookup_inner(path, clause, value, opts, table, column): except FieldFound: # Match found, loop has been shortcut. pass - except: # Any other exception; rethrow - raise else: # No match found. raise TypeError, "Cannot resolve keyword '%s' into field" % name - # Check to see if an intermediate join is required between current_table + # Check whether an intermediate join is required between current_table # and new_table. if intermediate_table: - joins[backend.quote_name(current_table)] = ( - backend.quote_name(intermediate_table), - "LEFT OUTER JOIN", - "%s.%s = %s.%s" % \ - (backend.quote_name(table), - backend.quote_name(current_opts.pk.column), - backend.quote_name(current_table), - backend.quote_name(intermediate_column)) + joins[qn(current_table)] = ( + qn(intermediate_table), "LEFT OUTER JOIN", + "%s.%s = %s.%s" % (qn(table), qn(current_opts.pk.column), qn(current_table), qn(intermediate_column)) ) if path: # There are elements left in the path. More joins are required. if len(path) == 1 and path[0] in (new_opts.pk.name, None) \ - and clause in ('exact', 'isnull') and not join_required: + and lookup_type in ('exact', 'isnull') and not join_required: # If the next and final name query is for a primary key, # and the search is for isnull/exact, then the current # (for N-1) or intermediate (for N-N) table can be used - # for the search - no need to join an extra table just + # for the search. No need to join an extra table just # to check the primary key. new_table = current_table else: # There are 1 or more name queries pending, and we have ruled out # any shortcuts; therefore, a join is required. - joins[backend.quote_name(new_table)] = ( - backend.quote_name(new_opts.db_table), - "INNER JOIN", - "%s.%s = %s.%s" % - (backend.quote_name(current_table), - backend.quote_name(join_column), - backend.quote_name(new_table), - backend.quote_name(new_column)) + joins[qn(new_table)] = ( + qn(new_opts.db_table), "INNER JOIN", + "%s.%s = %s.%s" % (qn(current_table), qn(join_column), qn(new_table), qn(new_column)) ) # If we have made the join, we don't need to tell subsequent # recursive calls about the column name we joined on. join_column = None # There are name queries remaining. Recurse deeper. - tables2, joins2, where2, params2 = lookup_inner(path, clause, value, new_opts, new_table, join_column) + joins2, where2, params2 = lookup_inner(path, lookup_type, value, new_opts, new_table, join_column) - tables.extend(tables2) joins.update(joins2) where.extend(where2) params.extend(params2) @@ -910,14 +895,9 @@ def lookup_inner(path, clause, value, opts, table, column): # RelatedObject is from a 1-N relation. # Join is required; query operates on joined table. column = new_opts.pk.name - joins[backend.quote_name(new_table)] = ( - backend.quote_name(new_opts.db_table), - "INNER JOIN", - "%s.%s = %s.%s" % - (backend.quote_name(current_table), - backend.quote_name(join_column), - backend.quote_name(new_table), - backend.quote_name(new_column)) + joins[qn(new_table)] = ( + qn(new_opts.db_table), "INNER JOIN", + "%s.%s = %s.%s" % (qn(current_table), qn(join_column), qn(new_table), qn(new_column)) ) current_table = new_table else: @@ -929,7 +909,7 @@ def lookup_inner(path, clause, value, opts, table, column): # Last query term is a related object from an N-N relation. # Join from intermediate table is sufficient. column = join_column - elif name == current_opts.pk.name and clause in ('exact', 'isnull') and current_column: + elif name == current_opts.pk.name and lookup_type in ('exact', 'isnull') and current_column: # Last query term is for a primary key. If previous iterations # introduced a current/intermediate table that can be used to # optimize the query, then use that table and column name. @@ -938,10 +918,10 @@ def lookup_inner(path, clause, value, opts, table, column): # Last query term was a normal field. column = field.column - where.append(get_where_clause(current_opts, clause, current_table + '.', column, value)) - params.extend(field.get_db_prep_lookup(clause, value)) + where.append(get_where_clause(current_opts, lookup_type, current_table + '.', column, value)) + params.extend(field.get_db_prep_lookup(lookup_type, value)) - return tables, joins, where, params + return joins, where, params def delete_objects(seen_objs): "Iterate through a list of seen classes, and remove any instances that are referred to" @@ -953,6 +933,7 @@ def delete_objects(seen_objs): backend = info.backend connection = info.connection cursor = connection.cursor() + qn = backend.quote_name seen_objs[cls] = seen_objs[cls].items() seen_objs[cls].sort() @@ -965,24 +946,21 @@ def delete_objects(seen_objs): for related in cls._meta.get_all_related_many_to_many_objects(): for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): cursor.execute("DELETE FROM %s WHERE %s IN (%s)" % \ - (backend.quote_name(related.field.m2m_db_table()), - backend.quote_name(related.field.m2m_reverse_name()), + (qn(related.field.m2m_db_table()), + qn(related.field.m2m_reverse_name()), ','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])), pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]) for f in cls._meta.many_to_many: for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): cursor.execute("DELETE FROM %s WHERE %s IN (%s)" % \ - (backend.quote_name(f.m2m_db_table()), - backend.quote_name(f.m2m_column_name()), - ','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])), + (qn(f.m2m_db_table()), qn(f.m2m_column_name()), + ','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])), pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]) for field in cls._meta.fields: if field.rel and field.null and field.rel.to in seen_objs: for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): cursor.execute("UPDATE %s SET %s=NULL WHERE %s IN (%s)" % \ - (backend.quote_name(cls._meta.db_table), - backend.quote_name(field.column), - backend.quote_name(cls._meta.pk.column), + (qn(cls._meta.db_table), qn(field.column), qn(cls._meta.pk.column), ','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])), pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]) @@ -993,6 +971,7 @@ def delete_objects(seen_objs): info = cls._meta.connection_info backend = info.backend connection = info.connection + qn = backend.quote_name cursor = connection.cursor() if connection not in dirty_conns: dirty_conns.append(connection) @@ -1001,9 +980,8 @@ def delete_objects(seen_objs): pk_list = [pk for pk,instance in seen_objs[cls]] for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): cursor.execute("DELETE FROM %s WHERE %s IN (%s)" % \ - (backend.quote_name(cls._meta.db_table), - backend.quote_name(cls._meta.pk.column), - ','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])), + (qn(cls._meta.db_table), qn(cls._meta.pk.column), + ','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])), pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]) # Last cleanup; set NULLs where there once was a reference to the object, diff --git a/django/template/__init__.py b/django/template/__init__.py index a1d1d402d0..e898fc7636 100644 --- a/django/template/__init__.py +++ b/django/template/__init__.py @@ -171,7 +171,7 @@ class Token(object): self.contents[:20].replace('\n', '')) def split_contents(self): - return smart_split(self.contents) + return list(smart_split(self.contents)) class Lexer(object): def __init__(self, template_string, origin): @@ -758,7 +758,7 @@ class DebugVariableNode(VariableNode): def generic_tag_compiler(params, defaults, name, node_class, parser, token): "Returns a template.Node subclass." - bits = token.contents.split()[1:] + bits = token.split_contents()[1:] bmax = len(params) def_len = defaults and len(defaults) or 0 bmin = bmax - def_len diff --git a/django/template/defaultfilters.py b/django/template/defaultfilters.py index 5d56ec0c49..bd9f55b1e9 100644 --- a/django/template/defaultfilters.py +++ b/django/template/defaultfilters.py @@ -133,7 +133,7 @@ def wordwrap(value, arg): """ Wraps words at specified line length - Argument: number of words to wrap the text at. + Argument: number of characters to wrap the text at. """ from django.utils.text import wrap return wrap(str(value), int(arg)) diff --git a/django/utils/translation/trans_null.py b/django/utils/translation/trans_null.py index e3a97d4912..0eb2b5a89a 100644 --- a/django/utils/translation/trans_null.py +++ b/django/utils/translation/trans_null.py @@ -14,5 +14,14 @@ string_concat = lambda *strings: ''.join([str(el) for el in strings]) activate = lambda x: None deactivate = install = lambda: None get_language = lambda: settings.LANGUAGE_CODE -get_date_formats = lambda: settings.DATE_FORMAT, settings.DATETIME_FORMAT, settings.TIME_FORMAT -get_partial_date_formats = lambda: settings.YEAR_MONTH_FORMAT, settings.MONTH_DAY_FORMAT +get_language_bidi = lambda: settings.LANGUAGE_CODE in settings.LANGUAGES_BIDI +get_date_formats = lambda: (settings.DATE_FORMAT, settings.DATETIME_FORMAT, settings.TIME_FORMAT) +get_partial_date_formats = lambda: (settings.YEAR_MONTH_FORMAT, settings.MONTH_DAY_FORMAT) +check_for_language = lambda x: True + +def to_locale(language): + p = language.find('-') + if p >= 0: + return language[:p].lower()+'_'+language[p+1:].upper() + else: + return language.lower() diff --git a/docs/i18n.txt b/docs/i18n.txt index 1382d6df0c..da6983dd59 100644 --- a/docs/i18n.txt +++ b/docs/i18n.txt @@ -224,6 +224,13 @@ block:: This will have {{ myvar }} inside. {% endblocktrans %} +If you need to bind more than one expression inside a ``blocktrans`` tag, +separate the pieces with ``and``:: + + {% blocktrans with book|title as book_t and author|title as author_t %} + This is {{ book_t }} by {{ author_t }} + {% endblocktrans %} + To pluralize, specify both the singular and plural forms with the ``{% plural %}`` tag, which appears within ``{% blocktrans %}`` and ``{% endblocktrans %}``. Example:: @@ -306,7 +313,7 @@ marked for translation. It creates (or updates) a message file in the directory ``conf/locale``. In the ``de`` example, the file will be ``conf/locale/de/LC_MESSAGES/django.po``. -If run over your project source tree or your appliation source tree, it will +If run over your project source tree or your application source tree, it will do the same, but the location of the locale directory is ``locale/LANG/LC_MESSAGES`` (note the missing ``conf`` prefix). @@ -349,7 +356,7 @@ A quick explanation: Long messages are a special case. There, the first string directly after the ``msgstr`` (or ``msgid``) is an empty string. Then the content itself will be written over the next few lines as one string per line. Those strings are -directlyconcatenated. Don't forget trailing spaces within the strings; +directly concatenated. Don't forget trailing spaces within the strings; otherwise, they'll be tacked together without whitespace! .. admonition:: Mind your charset @@ -452,7 +459,7 @@ Notes: ``de``. * Only languages listed in the `LANGUAGES setting`_ can be selected. If you want to restrict the language selection to a subset of provided - languages (because your appliaction doesn't provide all those languages), + languages (because your application doesn't provide all those languages), set ``LANGUAGES`` to a list of languages. For example:: LANGUAGES = ( @@ -465,6 +472,30 @@ Notes: en-us). .. _LANGUAGES setting: http://www.djangoproject.com/documentation/settings/#languages + + * If you define a custom ``LANGUAGES`` setting, as explained in the + previous bullet, it's OK to mark the languages as translation strings + -- but use a "dummy" ``gettext()`` function, not the one in + ``django.utils.translation``. You should *never* import + ``django.utils.translation`` from within your settings file, because that + module in itself depends on the settings, and that would cause a circular + import. + + The solution is to use a "dummy" ``gettext()`` function. Here's a sample + settings file:: + + gettext = lambda s: s + + LANGUAGES = ( + ('de', gettext('German')), + ('en', gettext('English')), + ) + + With this arrangement, ``make-messages.py`` will still find and mark + these strings for translation, but the translation won't happen at + runtime -- so you'll have to remember to wrap the languages in the *real* + ``gettext()`` in any code that uses ``LANGUAGES`` at runtime. + * The ``LocaleMiddleware`` can only select languages for which there is a Django-provided base translation. If you want to provide translations for your application that aren't already in the set of translations @@ -623,7 +654,7 @@ The ``javascript_catalog`` view ------------------------------- The main solution to these problems is the ``javascript_catalog`` view, which -sends out a JavaScript code library with functions that mimick the ``gettext`` +sends out a JavaScript code library with functions that mimic the ``gettext`` interface, plus an array of translation strings. Those translation strings are taken from the application, project or Django core, according to what you specify in either the {{{info_dict}}} or the URL. @@ -641,7 +672,7 @@ You hook it up like this:: Each string in ``packages`` should be in Python dotted-package syntax (the same format as the strings in ``INSTALLED_APPS``) and should refer to a package that contains a ``locale`` directory. If you specify multiple packages, all -those catalogs aremerged into one catalog. This is useful if you have +those catalogs are merged into one catalog. This is useful if you have JavaScript that uses strings from different applications. You can make the view dynamic by putting the packages into the URL pattern:: diff --git a/docs/model-api.txt b/docs/model-api.txt index 0dc98416a3..c4d57bf8c4 100644 --- a/docs/model-api.txt +++ b/docs/model-api.txt @@ -1225,6 +1225,33 @@ A few special cases to note about ``list_display``: return self.birthday.strftime('%Y')[:3] + "0's" decade_born_in.short_description = 'Birth decade' +``list_display_links`` +---------------------- + +Set ``list_display_links`` to control which fields in ``list_display`` should +be linked to the "change" page for an object. + +By default, the change list page will link the first column -- the first field +specified in ``list_display`` -- to the change page for each item. But +``list_display_links`` lets you change which columns are linked. Set +``list_display_links`` to a list or tuple of field names (in the same format as +``list_display``) to link. + +``list_display_links`` can specify one or many field names. As long as the +field names appear in ``list_display``, Django doesn't care how many (or how +few) fields are linked. The only requirement is: If you want to use +``list_display_links``, you must define ``list_display``. + +In this example, the ``first_name`` and ``last_name`` fields will be linked on +the change list page:: + + class Admin: + list_display = ('first_name', 'last_name', 'birthday') + list_display_links = ('first_name', 'last_name') + +Finally, note that in order to use ``list_display_links``, you must define +``list_display``, too. + ``list_filter`` --------------- diff --git a/docs/settings.txt b/docs/settings.txt index 9e1c6b529b..099196e56e 100644 --- a/docs/settings.txt +++ b/docs/settings.txt @@ -501,6 +501,28 @@ specifies which languages are available for language selection. See the Generally, the default value should suffice. Only set this setting if you want to restrict language selection to a subset of the Django-provided languages. +If you define a custom ``LANGUAGES`` setting, it's OK to mark the languages as +translation strings (as in the default value displayed above) -- but use a +"dummy" ``gettext()`` function, not the one in ``django.utils.translation``. +You should *never* import ``django.utils.translation`` from within your +settings file, because that module in itself depends on the settings, and that +would cause a circular import. + +The solution is to use a "dummy" ``gettext()`` function. Here's a sample +settings file:: + + gettext = lambda s: s + + LANGUAGES = ( + ('de', gettext('German')), + ('en', gettext('English')), + ) + +With this arrangement, ``make-messages.py`` will still find and mark these +strings for translation, but the translation won't happen at runtime -- so +you'll have to remember to wrap the languages in the *real* ``gettext()`` in +any code that uses ``LANGUAGES`` at runtime. + MANAGERS -------- @@ -738,6 +760,13 @@ Note that this is the time zone to which Django will convert all dates/times -- not necessarily the timezone of the server. For example, one server may serve multiple Django-powered sites, each with a separate time-zone setting. +Normally, Django sets the ``os.environ['TZ']`` variable to the time zone you +specify in the ``TIME_ZONE`` setting. Thus, all your views and models will +automatically operate in the correct time zone. However, if you're using the +manual configuration option (see below), Django will *not* touch the ``TZ`` +environment variable, and it'll be up to you to ensure your processes are +running in the correct environment. + USE_ETAGS --------- @@ -815,6 +844,15 @@ uppercase, with the same name as the settings described above. If a particular setting is not passed to ``configure()`` and is needed at some later point, Django will use the default setting value. +Configuring Django in this fashion is mostly necessary -- and, indeed, +recommended -- when you're using a piece of the framework inside a larger +application. + +Consequently, when configured via ``settings.configure()``, Django will not +make any modifications to the process environment variables. (See the +explanation of ``TIME_ZONE``, above, for why this would normally occur.) It's +assumed that you're already in full control of your environment in these cases. + Custom default settings ----------------------- diff --git a/docs/templates.txt b/docs/templates.txt index 4ba52b3263..6117bf7b84 100644 --- a/docs/templates.txt +++ b/docs/templates.txt @@ -47,7 +47,7 @@ explained later in this document.:: JavaScript and CSV. You can use the template language for any text-based format. - Oh, and one more thing: Making humans edit XML is masochistic! + Oh, and one more thing: Making humans edit XML is sadistic! Variables ========= diff --git a/docs/templates_python.txt b/docs/templates_python.txt index 2fa837e424..d353abb5bc 100644 --- a/docs/templates_python.txt +++ b/docs/templates_python.txt @@ -643,7 +643,7 @@ the current date/time, formatted according to a parameter given in the tag, in `strftime syntax`_. It's a good idea to decide the tag syntax before anything else. In our case, let's say the tag should be used like this:: -

      The time is {% current_time "%Y-%M-%d %I:%M %p" %}.

      +

      The time is {% current_time "%Y-%m-%d %I:%M %p" %}.

      .. _`strftime syntax`: http://www.python.org/doc/current/lib/module-time.html#l2h-1941 @@ -653,10 +653,10 @@ object:: from django import template def do_current_time(parser, token): try: - # Splitting by None == splitting by spaces. - tag_name, format_string = token.contents.split(None, 1) + # split_contents() knows not to split quoted strings. + tag_name, format_string = token.split_contents() except ValueError: - raise template.TemplateSyntaxError, "%r tag requires an argument" % token.contents[0] + raise template.TemplateSyntaxError, "%r tag requires a single argument" % token.contents[0] if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")): raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name return CurrentTimeNode(format_string[1:-1]) @@ -667,7 +667,13 @@ Notes: example. * ``token.contents`` is a string of the raw contents of the tag. In our - example, it's ``'current_time "%Y-%M-%d %I:%M %p"'``. + example, it's ``'current_time "%Y-%m-%d %I:%M %p"'``. + + * The ``token.split_contents()`` method separates the arguments on spaces + while keeping quoted strings together. The more straightforward + ``token.contents.split()`` wouldn't be as robust, as it would naively + split on *all* spaces, including those within quoted strings. It's a good + idea to always use ``token.split_contents()``. * This function is responsible for raising ``django.template.TemplateSyntaxError``, with helpful messages, for @@ -681,7 +687,7 @@ Notes: * The function returns a ``CurrentTimeNode`` with everything the node needs to know about this tag. In this case, it just passes the argument -- - ``"%Y-%M-%d %I:%M %p"``. The leading and trailing quotes from the + ``"%Y-%m-%d %I:%M %p"``. The leading and trailing quotes from the template tag are removed in ``format_string[1:-1]``. * The parsing is very low-level. The Django developers have experimented @@ -766,27 +772,24 @@ registers it with the template system. Our earlier ``current_time`` function could thus be written like this:: - # This version of do_current_time takes only a single argument and returns - # a string. + def current_time(format_string): + return datetime.datetime.now().strftime(format_string) - def do_current_time(token): - try: - # Splitting by None == splitting by spaces. - tag_name, format_string = token.contents.split(None, 1) - except ValueError: - raise template.TemplateSyntaxError, "%r tag requires an argument" % token.contents[0] - if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")): - raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name - return datetime.datetime.now().strftime(self.format_string[1:-1]) - - register.simple_tag(do_current_time) + register.simple_tag(current_time) In Python 2.4, the decorator syntax also works:: @register.simple_tag - def do_current_time(token): + def current_time(token): ... +A couple of things to note about the ``simple_tag`` helper function: + * Only the (single) argument is passed into our function. + * Checking for the required number of arguments, etc, has already been + done by the time our function is called, so we don't need to do that. + * The quotes around the argument (if any) have already been stripped away, + so we just receive a plain string. + Inclusion tags ~~~~~~~~~~~~~~ diff --git a/setup.py b/setup.py index 90448b1ddf..bdb5271294 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,8 @@ setup( packages = find_packages(exclude=['examples', 'examples.*']), package_data = { '': ['*.TXT'], - 'django.conf': ['locale/bn/LC_MESSAGES/*', + 'django.conf': ['locale/ar/LC_MESSAGES/*', + 'locale/bn/LC_MESSAGES/*', 'locale/cs/LC_MESSAGES/*', 'locale/cy/LC_MESSAGES/*', 'locale/da/LC_MESSAGES/*', diff --git a/tests/modeltests/m2m_and_m2o/models.py b/tests/modeltests/m2m_and_m2o/models.py index 7a685ecbd2..f43fb12d9e 100644 --- a/tests/modeltests/m2m_and_m2o/models.py +++ b/tests/modeltests/m2m_and_m2o/models.py @@ -28,24 +28,23 @@ API_TESTS = """ >>> r.save() >>> g = User(username='gustav') >>> g.save() + >>> i = Issue(num=1) >>> i.client = r ->>> i.validate() -{} >>> i.save() + >>> i2 = Issue(num=2) >>> i2.client = r ->>> i2.validate() -{} >>> i2.save() >>> i2.cc.add(r) + >>> i3 = Issue(num=3) >>> i3.client = g ->>> i3.validate() -{} >>> i3.save() >>> i3.cc.add(r) + >>> from django.db.models.query import Q + >>> Issue.objects.filter(client=r.id) [, ] >>> Issue.objects.filter(client=g.id) @@ -55,8 +54,8 @@ API_TESTS = """ >>> Issue.objects.filter(cc__id__exact=r.id) [, ] -# Queries that combine results from the m2m and the m2o relationship. -# 3 ways of saying the same thing: +# These queries combine results from the m2m and the m2o relationships. +# They're three ways of saying the same thing. >>> Issue.objects.filter(Q(cc__id__exact=r.id) | Q(client=r.id)) [, , ] >>> Issue.objects.filter(cc__id__exact=r.id) | Issue.objects.filter(client=r.id) diff --git a/tests/othertests/templates.py b/tests/othertests/templates.py index d3b09c5310..3d23d8123b 100644 --- a/tests/othertests/templates.py +++ b/tests/othertests/templates.py @@ -1,5 +1,9 @@ from django.conf import settings +if __name__ == '__main__': + # When running this file in isolation, we need to set up the configuration + # before importing 'template'. + settings.configure() from django import template from django.template import loader @@ -538,10 +542,10 @@ TEMPLATE_TESTS = { ### TIMESINCE TAG ################################################## # Default compare with datetime.now() - 'timesince01' : ('{{ a|timesince }}', {'a':datetime.now() + timedelta(minutes=-1)}, '1 minute'), - 'timesince02' : ('{{ a|timesince }}', {'a':(datetime.now() - timedelta(days=1))}, '1 day'), + 'timesince01' : ('{{ a|timesince }}', {'a':datetime.now() + timedelta(minutes=-1, seconds = -10)}, '1 minute'), + 'timesince02' : ('{{ a|timesince }}', {'a':(datetime.now() - timedelta(days=1, minutes = 1))}, '1 day'), 'timesince03' : ('{{ a|timesince }}', {'a':(datetime.now() - - timedelta(hours=1, minutes=25))}, '1 hour, 25 minutes'), + timedelta(hours=1, minutes=25, seconds = 10))}, '1 hour, 25 minutes'), # Compare to a given parameter 'timesince04' : ('{{ a|timesince:b }}', {'a':NOW + timedelta(days=2), 'b':NOW + timedelta(days=1)}, '1 day'), @@ -552,9 +556,9 @@ TEMPLATE_TESTS = { ### TIMEUNTIL TAG ################################################## # Default compare with datetime.now() - 'timeuntil01' : ('{{ a|timeuntil }}', {'a':datetime.now() + timedelta(minutes=2)}, '2 minutes'), - 'timeuntil02' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(days=1))}, '1 day'), - 'timeuntil03' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(hours=8, minutes=10))}, '8 hours, 10 minutes'), + 'timeuntil01' : ('{{ a|timeuntil }}', {'a':datetime.now() + timedelta(minutes=2, seconds = 10)}, '2 minutes'), + 'timeuntil02' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(days=1, seconds = 10))}, '1 day'), + 'timeuntil03' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(hours=8, minutes=10, seconds = 10))}, '8 hours, 10 minutes'), # Compare to a given parameter 'timeuntil04' : ('{{ a|timeuntil:b }}', {'a':NOW - timedelta(days=1), 'b':NOW - timedelta(days=2)}, '1 day'), @@ -621,5 +625,4 @@ def run_tests(verbosity=0, standalone=False): raise Exception, msg if __name__ == "__main__": - settings.configure() run_tests(1, True) diff --git a/tests/runtests.py b/tests/runtests.py index b712d1352a..8dc48415ee 100755 --- a/tests/runtests.py +++ b/tests/runtests.py @@ -154,8 +154,9 @@ class TestRunner: # Manually set INSTALLED_APPS to point to the test models. settings.INSTALLED_APPS = ALWAYS_INSTALLED_APPS + ['.'.join(a) for a in get_test_models()] - # Manually set DEBUG = False. + # Manually set DEBUG and USE_I18N. settings.DEBUG = False + settings.USE_I18N = True self.output(0, "Running tests with database %r" % settings.DATABASE_ENGINE)
      {{ model.name }}{{ model.name|escape }}{{ model.name }}{{ model.name|escape }}
      {{ field.name }} {{ field.data_type }}{% if field.verbose %}{{ field.verbose }}{% endif %}{% if field.help_text %} - {{ field.help_text }}{% endif %}{% if field.verbose %}{{ field.verbose|escape }}{% endif %}{% if field.help_text %} - {{ field.help_text|escape }}{% endif %}