From 41022186f002490f50e453473da96a4e7f86b93a Mon Sep 17 00:00:00 2001 From: dv Date: Thu, 1 May 2014 12:13:42 +0800 Subject: [PATCH 01/57] add a little zh_TW translation for wagtailadmin --- .../locale/zh_TW/LC_MESSAGES/django.mo | Bin 0 -> 12227 bytes .../locale/zh_TW/LC_MESSAGES/django.po | 837 ++++++++++++++++++ 2 files changed, 837 insertions(+) create mode 100644 wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.mo create mode 100644 wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.po diff --git a/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.mo b/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..c5459c29eea40694e527718aec301ee523bebc57 GIT binary patch literal 12227 zcmb`MdvILUdB9J?GY-#$lB6NY4Fqfx>tO={gt0MxBu+3m*gy$Q&DHLew6NM0`><>X zLAH@CTb3;wTYg9c$=D$LkYvDEmTW5}W!ir_q|+udZE4e)?A=G3mT5ZEmNwJr?>p!0 z-CbEWX{L8{_IJ;@=lPxQ`_6Z-{{Ax;?^axWq#H=Txmc;cgdcp0AFdf!DzymCgipd4 z{04j31#8H6z$@S=`~rLr$~=Do`BVSO z&+o%eQYcIR5=0bgI=mFlf>Q4``+O0U^*(6xF(~!dSUwMBKITerCGbut?e4X_-}0MK=Jx;;IXwZTod++1&5$LiXP~s-0Hyy9 zDE%IUH^ak_KlM|~43u{N34aexLwUXi9m~b=bL5|b(r!HzdG)|1I09u|U!bv+-wb8F z^P%kP5-9U_q3l}=ybX54&%-}~vW~xlB46L;{{_lA{~bzy>Uz`9Wl-jEJrsH03S~d< zf>LiGl=*xc-U1(mGT!r0^zb;OOLZ2?xPJxN67_+7{vnik{04p>Uc%y+zz~%F4?}5p z97;c@;2rRN_zidoi;{8Y!s#$%^PM*TCcK^Uzk##h)d)@Ub72*H2FgCY0z>dUD0Vs% zVak54gtDJ4Q1*E>6gfQyMK0}7*0~Q#z1N_~=O~nVC*chE$MEa$AE5)Ur*pB_JE8Q` z2t_ZRgZ!y3e#DO6u=ziOBjhs>QK{WHu`oOem%?kmWY+fttRvq6Mb1Bg-JekE=WsFk zMwH?)cnnJZ6358-J5bi~Fr=zl1!er_A)-@#5SOG*SiT2EUO$7fPj`P+DgM-b{M--g zq3q8gDEsmOl>RTi(ePSGk@_-}{_le_-^VSZmM_@nJE82?5h(rqwSAt2q8A@Q>E~*k zh3LZ!DDr;@%KRR;d=kn!8g0H6O1mH0{2t36SssEiucJ`fO+ZAh-iI=eU)kp$L7B%D zUo-o6Bb55{U@d$Q%JUbX%xAY{9~3)%)$%7$+Witr|NmwwN-FKHw7d?=yuJvfUNw~c zy2n2Mo~3KqWErpHZZUd! zE0p{K%O@aPqtZ~;xfhE3Mxp5O&mbzTeg*#!UXHTJd_0J$s05UK?1Hl1Jy7Ix7)rY_ zD0=a8DC@tNNnHwWvb@!Dw&h)x^P!Bh1WLavp!C~d%U46`XM-)@0vST>hvGlph2m%b z1IoT$I@8p@0ZREzQ2L)^%jd%g`6X}x9I@rUhMyw;5tRBD;e5pZT*Hs7>mJAuDq^|Q za@;Zl#jjk+kJP^#-Ub^Xs-t?L$mPfIA@~a@`&cu}*x$FHtn(?$XW$j&*FafUyUq7P zndhL*zX?TN6Yy^MK6K!xn1u9yE4&LXgwoFsEO$bg*C3R6{W%mr@GIC4uc|itF$`Cd ze;3Y$pQ|zTRzmSBtD*FJ41NOMK?;-PdYVKteIXuwEwL1c9?B(px|_5`GF;y>(7%iM z6+b$UB;);%w1L!1dW3W*NiJDCTX)VCvL&+DqQ{qzt|nbhlIsr))RQnu5?fqPVmbPH zh~KsL{#p2_y%$|Y)LJKIL$TE)No0yC>PzI(PI}Q~_4&Mq`=vH75SuJsvJcH9Ie)g3 zwvog(w+G(JF#r{^-#@=dK_|l3epit4VQE6G?1Wt}99R z>N|WAe2Mg3lIUOq>6@e(Q|H|(E?V*(#`c=VrJ5bH&8@wl@upuCaWu& zRd%vG;jNB%t&v!xGyUcnsYoj7%}h?8{T~I3YLYq+>1V`e-EC=6YuJl=DON2*%XH_TzpBiu zR8ddEjYdTyBB`ViVFJ-dVwEEN?R)$`v@922F!O~?Zj2pVZnZ(#d{H}!c_VPEF|r@& zq~7*uyphRQQ_TxKEz(LDHKHIMr;4iu6y#WG%4;rVVhb=YYl~`;n{29&yNNJ&DNilZ%3x7m%_vDEr4~h!Zhe%wC&FGr44Xxi z^ggK;#Y5?4FP7pi;WnzpsHgrZ>5a}x%hD{QmXyp*wz#o*LHXPoo!1TGiKMeU5_&qR z7K>#Yqgx!i;9M5RFaac!M35qLFVXC{^ zGhMD}iN+HF6U74A!lG}{-m~1f*hUHQh_X57sW3@e6^>^~Jkc1(mx?ydSKo>=m8H$n zm0B8OZYd+Fr6P*JSv}w;Q%-X{9BGJn;W{=VO2H}$W+v4G7(qOp5~4cGyjWT-lXWc< zxyeu2zUgc@-by`rkZw^AdaaVEBgBtDwD+DRK#4_B*)M4Qxd zniN}d!pKn|hfOM;a-+dtGX~KKT3(2w6 zQ1qxFZDbXl1*es+h0r`>i4~Os_cUpQbW0dJvvWy0ZmVlFztoMMw_dq+$=XrKc@d9s zc+`8vH9H)1TCv3ABBr@s^E@qpxi#F`qon8(oYn|_n#M^)&zXpy!oi4ulK4KftNgyW z19tD0yNr;cg7udn<71QQPzVcYNJmSL^nt9F7+yQF;yBuE@xEXHlKNgI&1VdEDI!=GmBVSGy@UK?gR(F?(q? zL9K{1$~jx4_^HR-#uSc`B2M#Uy1Cg+tW_&wk(L$@A*_fe5^HA_qlQ>KHFflaUWfn! z&*r!$Y;rhao81@+qeC{A4&ze3jnmjVQDdm~02OuBJ2^>b)rypx zVhauG)CwIXPO>t!(nd?pjmF2!Ox{?E`p##Yzgw&7ie~o6EE~-=u~qoDtoCu;6}`{L zbXTla)}8Tu?2(8*lun2?;w`4|E@h2~hY5M5MVVI#r*#bCB@!IC=c{bIh^?xPQF}?p zw6fDTnu;+Qg=ltDp{8o5Xvhg>Ct<1#!Mt^}9-O*%A((HxF&0URyVSKP*P0nF1}*Zc zVB)DJFWQ1H!X~gk#v(G3qdtu|;v9V#CoQLA-uB1{JYqPKY>B#SgE3m<3}T=QO3_Rw z8BG%};>4o_T;a8hErFz3DX%$dB`2SHq!{Cu?#g^a@RXBVJ%TMI)uR&L8=s?Zqr5Yy z$Gm8WV_l3~ye02TnD{CQI%Xz|X74Oqwn9B7eq994TAgBiADCX{k$j=La`4dETCE&& zU8gDGHQbB25f$lUcvU(P#q8#hX9v8wHSWCm>TxeQivK!wXv%`4P?q_)ef!a` zEwUOdZ<%*p@T|qWHR{Dq@mRkCo!gW^PkT%!BGHfRi@f+m!p38L)B02W(jwa%kHySU zk5si%Rj6RK^H?O+gug1avyMzo;ZGAuOjFvc=t9TLYPyi z7$Zd2e$`YihRb>%f|lV(SSE2^AECbz6ysI>k$?j~F2{P+(s0$ISPu4HSG0v`4|^@~ zM5=08vM~~_xbsbLwjE{(3FfGzp`tRwmq7l9%mxqRwdzufF}xJML<7 z<`(bnYm~Q@YV3C&)nkombhB!u=Qh_l3!5S_ViIRYQ!3R`S5wp4+FFfZW64N^w?i-niY zX15*kPrjKO-|lbUQD|G|cZ_7$5ArCt>x6%-yRd#JH*`ERdQ9cte$C&0(jq@}mTpw` z=7d-Q{IJ)gEGyaYl)HXJc{ewM)4TBXAf?g+&qB3Xt8PDH7 zoEbmlZ|}*z)4|mJ(GA&S2Pyw$+j?{3k8I40cI7vm$&7C^{pW`!3VVh=JiV13O!M67 zp8VMze)l$iV^{X*fa!-GRH1Eueqxghl^YoHhxT)me+}XE7xo>r-FNT#@boK_Yvf)> zB7^yfeKNzHTmANTvYXqoeVc>TRLaQj-ZQ_Vi|mHC7$@k3eVa)4X~CcB4v0b~Byc9refBtpz~_Mj}vD4_-O3pU*rmHIU` z&-3bJ9%eUpW_RpWf%TT`%|G4dcMk`OSQyY#$q%1IDw)wOBD=FM`R#|Y-F>;Y59Eit zRQ^b3{`4qCq7Vm8m-0p-3ccg>mYEn34{>%Qt_4XO`A^-zAAKvo?-i9ju^rb|iE>Bh zhzb^cimmo>&r33@a3%i4-u%!=W^AK2)zNXbTlu|b{SEBF_MNQEs-Sj*%HP;t@CL|KNUQ%-5o%SIY0+ks0l@PjzOC%^*0G zVx%HWMeCJ+mOb01vTqKE4>|c}X5wZ4*xtYrl-)#*8{1TWI%1WM-+mmKlz%;vwad9= zUYN+ypV4tKsB@oa&7NFr<~wBr?SrR!l0R@H+qpA0{&LB^PVUy6S^m&KwtsZ0F3O$T zIa5XIB0sU5v0m1NCZp21W1Ic6?WRlpY_tuD2BPz~ALeK%+W1)I>v*{WG97J`Z6Yy_ zl+*joCNM-{{i`zB(vZ6bRmB!MG5ZOUwy#h?d%naVHA+Bb|jkeT6O}fjtOgEU?+~ z!-Sobx%HniQk8mB`@0J@GT}+^9m!g8i33pv>u&WOCp%HT~ZH-1;$Fs6AhH?{IF{adRAI zPLE~#y8L~E#0R;dfn4`SQ6+!)R4@|rwRW$M!buvck3=IQS=GxM3j4aX9LBCaxT5v)g>d~ZJ%Q`ogHKRk?arNyj!M`-F%iQ5|bC&_F=o_C$2oE z6rD0E<^;isXldVu!oYCu;25f#?Kv%;etax%ICA)6e zu3FY{?A0m#=V5=>usAUK=o|50ZlhQB)$i&jd{o)~O~g#fglek7UzcYB&A`)?B6mXI z2|CHQwJXBSTwiC=cj$~vW^5w2nULYwKz?Fdq3ul!S6+O|z6CL>q78HQ$r6oK<=z_4 zoj5KrHlZ~=5mB0bqrH4!DgK-0+zLjo!~tc-+cKv**oX^!4+>s(5TN-eB-XzFMK;5n znMOxcP+Be(nVx;0(O$)b9Oa5FmOQDFaonccDIQxvmWPwp7ae??_=hM+yqoq&#ScAV z|7Uy6r2SLxWJY)S?QiAR?IM0MP0OQ7qXTFSDuE&w`!KJGW--R^5)nxZUwoY;AT>=z zkIJSZ`X`%!IZo{0nUR4Mk-=+QLn=RkJ4TGRrh<6K!oWKmuI954%^Y^y9@V_x>9<9* z6V=KJLLa%}ZwUmn+$ECOb&8o_gsfY1M;`}9mHZuhWs>EMt>4tm%t2mOL;HMr3DnWE liKGi#hx3OIikTnjrjO literal 0 HcmV?d00001 diff --git a/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.po b/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.po new file mode 100644 index 000000000..de09aeb0c --- /dev/null +++ b/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.po @@ -0,0 +1,837 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: Wagtail\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-03-14 23:02+0200\n" +"PO-Revision-Date: 2014-05-01 12:09+0000\n" +"Last-Translator: wdv4758h \n" +"Language-Team: Chinese (http://www.transifex.com/projects/p/wagtail/language/zh/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: .\edit_handlers.py:81 .\edit_handlers.py:130 .\edit_handlers.py:134 +msgid "Please type a valid time" +msgstr "請輸入一個有效的時間" + +#: .\edit_handlers.py:724 +msgid "Common page configuration" +msgstr "一般頁面設定" + +#: .\forms.py:18 +msgid "Search term" +msgstr "搜尋關鍵字" + +#: .\forms.py:42 +msgid "Enter your username" +msgstr "請輸入您的帳號" + +#: .\forms.py:45 +msgid "Enter password" +msgstr "請輸入密碼" + +#: .\forms.py:50 +msgid "Enter your email address to reset your password" +msgstr "請輸入您的電子信箱來重新設定密碼" + +#: .\forms.py:59 +msgid "Please fill your email address." +msgstr "請輸入您的電子信箱" + +#: .\forms.py:72 +msgid "" +"Sorry, you cannot reset your password here as your user account is managed " +"by another server." +msgstr "對不起,您不能在此重新設定您的密碼,因為您的帳號是由其他伺服器所管理。" + +#: .\forms.py:75 +msgid "This email address is not recognised." +msgstr "找不到這個電子信箱。" + +#: .\templates\wagtailadmin\base.html:7 .\templates\wagtailadmin\home.html:4 +msgid "Dashboard" +msgstr "Dashboard" + +#: .\templates\wagtailadmin\base.html:31 +msgid "Menu" +msgstr "選單" + +#: .\templates\wagtailadmin\home.html:22 +#, python-format +msgid "Welcome to the %(site_name)s Wagtail CMS" +msgstr "歡迎進入 %(site_name)s 的 Wagtail 內容管理系統" + +#: .\templates\wagtailadmin\home.html:33 +msgid "" +"This is your dashboard on which helpful information about content you've " +"created will be displayed." +msgstr "這是您的 Dashboard,會顯示對於已建立的內容有幫助的訊息。" + +#: .\templates\wagtailadmin\login.html:4 +#: .\templates\wagtailadmin\login.html:55 +msgid "Sign in" +msgstr "登入" + +#: .\templates\wagtailadmin\login.html:18 +msgid "Your username and password didn't match. Please try again." +msgstr "您的帳號和密碼輸入錯誤,請再試一次。" + +#: .\templates\wagtailadmin\login.html:26 +msgid "Sign in to Wagtail" +msgstr "登入 Wagtail" + +#: .\templates\wagtailadmin\login.html:42 +msgid "Forgotten it?" +msgstr "忘记了?" + +#: .\templates\wagtailadmin\account\account.html:4 +msgid "Account" +msgstr "账号" + +#: .\templates\wagtailadmin\account\account.html:11 +msgid "Set gravatar" +msgstr "设置gravatar" + +#: .\templates\wagtailadmin\account\account.html:15 +msgid "" +"Your avatar image is provided by Gravatar and is connected to your email " +"address. With a Gravatar account you can set an avatar for any number of " +"other email addresses you use." +msgstr "您的头像图片是由Gravatar提供的,并且关联了您的电子邮件地址。一个Gravatar账号可以设置多个电子邮件地址的头像图片。" + +#: .\templates\wagtailadmin\account\account.html:23 +#: .\templates\wagtailadmin\account\change_password.html:4 +msgid "Change password" +msgstr "修改密码" + +#: .\templates\wagtailadmin\account\account.html:27 +msgid "Change the password you use to log in." +msgstr "修改您用于登录的密码。" + +#: .\templates\wagtailadmin\account\change_password.html:16 +msgid "Change Password" +msgstr "修改密码" + +#: .\templates\wagtailadmin\account\change_password.html:19 +msgid "" +"Your password can't be changed here. Please contact a site administrator." +msgstr "您的密码不能在此更改。请联系网站管理员。" + +#: .\templates\wagtailadmin\account\password_reset\complete.html:4 +#: .\templates\wagtailadmin\account\password_reset\confirm.html:42 +#: .\templates\wagtailadmin\account\password_reset\done.html:4 +#: .\templates\wagtailadmin\account\password_reset\form.html:37 +msgid "Reset password" +msgstr "重置密码" + +#: .\templates\wagtailadmin\account\password_reset\complete.html:15 +msgid "Password change successful" +msgstr "密码修改成功" + +#: .\templates\wagtailadmin\account\password_reset\complete.html:16 +msgid "Login" +msgstr "登录" + +#: .\templates\wagtailadmin\account\password_reset\confirm.html:4 +#: .\templates\wagtailadmin\account\password_reset\confirm.html:26 +msgid "Set your new password" +msgstr "设置你的新密码" + +#: .\templates\wagtailadmin\account\password_reset\confirm.html:19 +msgid "The passwords do not match. Please try again." +msgstr "两个密码不匹配,请重试。" + +#: .\templates\wagtailadmin\account\password_reset\done.html:15 +msgid "Check your email" +msgstr "检查您的电子邮件" + +#: .\templates\wagtailadmin\account\password_reset\done.html:16 +msgid "A link to reset your password has been emailed to you." +msgstr "一个用于重置密码的链接已经发送到您的电子邮箱中" + +#: .\templates\wagtailadmin\account\password_reset\email.txt:2 +msgid "Please follow the link below to reset your password" +msgstr "请点击下面的链接来重置您的密码" + +#: .\templates\wagtailadmin\account\password_reset\email_subject.txt:2 +msgid "Password reset" +msgstr "密码已重置" + +#: .\templates\wagtailadmin\account\password_reset\form.html:27 +msgid "Reset your password" +msgstr "重置您的密码" + +#: .\templates\wagtailadmin\chooser\_link_types.html:5 +#: .\templates\wagtailadmin\chooser\_link_types.html:7 +msgid "Internal link" +msgstr "内部链接" + +#: .\templates\wagtailadmin\chooser\_link_types.html:11 +#: .\templates\wagtailadmin\chooser\_link_types.html:13 +msgid "External link" +msgstr "外部链接" + +#: .\templates\wagtailadmin\chooser\_link_types.html:17 +#: .\templates\wagtailadmin\chooser\_link_types.html:19 +msgid "Email link" +msgstr "电子邮件链接" + +#: .\templates\wagtailadmin\chooser\_search_form.html:7 +#: .\templates\wagtailadmin\pages\search.html:3 +#: .\templates\wagtailadmin\pages\search.html:16 +#: .\templatetags\wagtailadmin_nav.py:44 +msgid "Search" +msgstr "搜索" + +#: .\templates\wagtailadmin\chooser\_search_results.html:3 +#: .\templatetags\wagtailadmin_nav.py:43 +msgid "Explorer" +msgstr "浏览" + +#: .\templates\wagtailadmin\chooser\_search_results.html:5 +#: .\templates\wagtailadmin\pages\index.html:15 +#: .\templates\wagtailadmin\pages\move_choose_destination.html:10 +msgid "Home" +msgstr "主页" + +#: .\templates\wagtailadmin\chooser\_search_results.html:13 +#, python-format +msgid "" +"\n" +" There is one match\n" +" " +msgid_plural "" +"\n" +" There are %(counter)s matches\n" +" " +msgstr[0] "" + +#: .\templates\wagtailadmin\chooser\browse.html:2 +#: .\templates\wagtailadmin\chooser\search.html:2 +#: .\templates\wagtailadmin\edit_handlers\page_chooser_panel.html:13 +msgid "Choose a page" +msgstr "选择一个页面" + +#: .\templates\wagtailadmin\chooser\email_link.html:2 +msgid "Add an email link" +msgstr "添加一个电子邮件链接" + +#: .\templates\wagtailadmin\chooser\email_link.html:14 +#: .\templates\wagtailadmin\chooser\external_link.html:14 +msgid "Insert link" +msgstr "插入一个链接" + +#: .\templates\wagtailadmin\chooser\external_link.html:2 +msgid "Add an external link" +msgstr "添加一个外部链接" + +#: .\templates\wagtailadmin\edit_handlers\chooser_panel.html:20 +msgid "Clear choice" +msgstr "清除选择" + +#: .\templates\wagtailadmin\edit_handlers\chooser_panel.html:22 +msgid "Choose another item" +msgstr "选择其他选项" + +#: .\templates\wagtailadmin\edit_handlers\chooser_panel.html:27 +msgid "Choose an item" +msgstr "选择一个选项" + +#: .\templates\wagtailadmin\edit_handlers\inline_panel_child.html:5 +msgid "Move up" +msgstr "向上移动" + +#: .\templates\wagtailadmin\edit_handlers\inline_panel_child.html:6 +msgid "Move down" +msgstr "向下移动" + +#: .\templates\wagtailadmin\edit_handlers\inline_panel_child.html:8 +#: .\templates\wagtailadmin\pages\confirm_delete.html:7 +#: .\templates\wagtailadmin\pages\edit.html:36 +#: .\templates\wagtailadmin\pages\list.html:68 +#: .\templates\wagtailadmin\pages\list.html:188 +msgid "Delete" +msgstr "删除" + +#: .\templates\wagtailadmin\edit_handlers\page_chooser_panel.html:12 +msgid "Choose another page" +msgstr "选择另外一个页面" + +#: .\templates\wagtailadmin\home\pages_for_moderation.html:5 +msgid "Pages awaiting moderation" +msgstr "这些页面在等待审核" + +#: .\templates\wagtailadmin\home\pages_for_moderation.html:13 +#: .\templates\wagtailadmin\home\recent_edits.html:12 +#: .\templates\wagtailadmin\pages\list.html:101 +msgid "Title" +msgstr "标题" + +#: .\templates\wagtailadmin\home\pages_for_moderation.html:14 +#: .\templates\wagtailadmin\pages\list.html:22 +msgid "Parent" +msgstr "上一级" + +#: .\templates\wagtailadmin\home\pages_for_moderation.html:15 +#: .\templates\wagtailadmin\pages\list.html:24 +#: .\templates\wagtailadmin\pages\list.html:116 +msgid "Type" +msgstr "类型" + +#: .\templates\wagtailadmin\home\pages_for_moderation.html:16 +msgid "Edited" +msgstr "" + +#: .\templates\wagtailadmin\home\pages_for_moderation.html:23 +#: .\templates\wagtailadmin\home\recent_edits.html:21 +#: .\templates\wagtailadmin\pages\list.html:167 +#: .\templates\wagtailadmin\pages\list.html:176 +msgid "Edit this page" +msgstr "编辑这个页面" + +#: .\templates\wagtailadmin\home\pages_for_moderation.html:28 +#: .\templates\wagtailadmin\pages\_moderator_userbar.html:12 +msgid "Approve" +msgstr "通过" + +#: .\templates\wagtailadmin\home\pages_for_moderation.html:34 +#: .\templates\wagtailadmin\pages\_moderator_userbar.html:17 +msgid "Reject" +msgstr "拒绝" + +#: .\templates\wagtailadmin\home\pages_for_moderation.html:37 +#: .\templates\wagtailadmin\home\recent_edits.html:23 +#: .\templates\wagtailadmin\pages\_moderator_userbar.html:9 +#: .\templates\wagtailadmin\pages\list.html:56 +#: .\templates\wagtailadmin\pages\list.html:176 +msgid "Edit" +msgstr "编辑" + +#: .\templates\wagtailadmin\home\pages_for_moderation.html:38 +#: .\templates\wagtailadmin\pages\create.html:24 +#: .\templates\wagtailadmin\pages\edit.html:42 +msgid "Preview" +msgstr "预览" + +#: .\templates\wagtailadmin\home\recent_edits.html:5 +msgid "Your most recent edits" +msgstr "你最近的编辑" + +#: .\templates\wagtailadmin\home\recent_edits.html:13 +msgid "Date" +msgstr "日期" + +#: .\templates\wagtailadmin\home\recent_edits.html:14 +#: .\templates\wagtailadmin\pages\list.html:25 +#: .\templates\wagtailadmin\pages\list.html:128 +msgid "Status" +msgstr "状态" + +#: .\templates\wagtailadmin\home\recent_edits.html:25 +#: .\templates\wagtailadmin\pages\list.html:59 +#: .\templates\wagtailadmin\pages\list.html:179 +msgid "View draft" +msgstr "查看草稿" + +#: .\templates\wagtailadmin\home\recent_edits.html:28 +#: .\templates\wagtailadmin\pages\list.html:62 +#: .\templates\wagtailadmin\pages\list.html:182 +msgid "View live" +msgstr "查看在线版" + +#: .\templates\wagtailadmin\home\site_summary.html:3 +msgid "Site summary" +msgstr "网站摘要" + +#: .\templates\wagtailadmin\home\site_summary.html:6 +#, python-format +msgid "" +"\n" +" %(total_pages)s Page\n" +" " +msgid_plural "" +"\n" +" %(total_pages)s Pages\n" +" " +msgstr[0] "" + +#: .\templates\wagtailadmin\home\site_summary.html:13 +#, python-format +msgid "" +"\n" +" %(total_images)s Image\n" +" " +msgid_plural "" +"\n" +" %(total_images)s Images\n" +" " +msgstr[0] "" + +#: .\templates\wagtailadmin\home\site_summary.html:20 +#, python-format +msgid "" +"\n" +" %(total_docs)s Document\n" +" " +msgid_plural "" +"\n" +" %(total_docs)s Documents\n" +" " +msgstr[0] "" + +#: .\templates\wagtailadmin\notifications\approved.html:1 +#, python-format +msgid "The page \"%(title)s\" has been approved" +msgstr "这个页面 \"%(title)s\" 已经被通过" + +#: .\templates\wagtailadmin\notifications\approved.html:2 +#, python-format +msgid "The page \"%(title)s\" has been approved." +msgstr "这个页面 \"%(title)s\" 已经被通过" + +#: .\templates\wagtailadmin\notifications\approved.html:4 +msgid "You can view the page here:" +msgstr "你可以在此查看这个页面" + +#: .\templates\wagtailadmin\notifications\rejected.html:1 +#, python-format +msgid "The page \"%(title)s\" has been rejected" +msgstr "这个页面 \"%(title)s\" 已经被拒绝" + +#: .\templates\wagtailadmin\notifications\rejected.html:2 +#, python-format +msgid "The page \"%(title)s\" has been rejected." +msgstr "这个页面 \"%(title)s\" 已经被拒绝" + +#: .\templates\wagtailadmin\notifications\rejected.html:4 +#: .\templates\wagtailadmin\notifications\submitted.html:5 +msgid "You can edit the page here:" +msgstr "你可以在此编辑这个页面:" + +#: .\templates\wagtailadmin\notifications\submitted.html:1 +#, python-format +msgid "The page \"%(page)s\" has been submitted for moderation" +msgstr "这个页面 \"%(page)s\" 已经提交审核" + +#: .\templates\wagtailadmin\notifications\submitted.html:2 +#, python-format +msgid "The page \"%(page)s\" has been submitted for moderation." +msgstr "这个页面 \"%(page)s\" 已经提交审核。" + +#: .\templates\wagtailadmin\notifications\submitted.html:4 +msgid "You can preview the page here:" +msgstr "你可以在此预览这页:" + +#: .\templates\wagtailadmin\pages\_moderator_userbar.html:4 +#, python-format +msgid "" +"\n" +" Previewing '%(title)s', submitted by %(submitted_by)s on %(submitted_on)s.\n" +" " +msgstr "\n 预览 '%(title)s', %(submitted_by)s 在 %(submitted_on)s 提交.\n " + +#: .\templates\wagtailadmin\pages\add_subpage.html:6 +#, python-format +msgid "Create a page in %(title)s" +msgstr "以 %(title)s 为题创建一个页面" + +#: .\templates\wagtailadmin\pages\add_subpage.html:9 +msgid "Create a page in" +msgstr "在这创建一个页面" + +#: .\templates\wagtailadmin\pages\add_subpage.html:13 +msgid "Choose which type of page you'd like to create." +msgstr "选择你希望创建哪个类型的页面。" + +#: .\templates\wagtailadmin\pages\add_subpage.html:26 +#, python-format +msgid "Pages using %(page_type)s" +msgstr "%(page_type)s 类的页面" + +#: .\templates\wagtailadmin\pages\confirm_delete.html:3 +#, python-format +msgid "Delete %(title)s" +msgstr "删除%(title)s" + +#: .\templates\wagtailadmin\pages\confirm_delete.html:12 +msgid "Are you sure you want to delete this page?" +msgstr "你确定你要删除此页吗?" + +#: .\templates\wagtailadmin\pages\confirm_delete.html:14 +#, python-format +msgid "" +"\n" +" This will also delete one more subpage.\n" +" " +msgid_plural "" +"\n" +" This will also delete %(descendant_count)s more subpages.\n" +" " +msgstr[0] "" + +#: .\templates\wagtailadmin\pages\confirm_delete.html:22 +msgid "" +"Alternatively you can unpublish the page. This removes the page from public " +"view and you can edit or publish it again later." +msgstr "你页可以取消发布此页。此页将不能从外部访问,你可以编辑后再次发布。" + +#: .\templates\wagtailadmin\pages\confirm_delete.html:26 +msgid "Delete it" +msgstr "删除" + +#: .\templates\wagtailadmin\pages\confirm_delete.html:26 +msgid "Unpublish it" +msgstr "取消发布" + +#: .\templates\wagtailadmin\pages\confirm_move.html:3 +#, python-format +msgid "Move %(title)s" +msgstr "移动 %(title)s" + +#: .\templates\wagtailadmin\pages\confirm_move.html:6 +#: .\templates\wagtailadmin\pages\list.html:65 +#: .\templates\wagtailadmin\pages\list.html:185 +msgid "Move" +msgstr "移动" + +#: .\templates\wagtailadmin\pages\confirm_move.html:11 +#, python-format +msgid "Are you sure you want to move this page into '%(title)s'?" +msgstr "你确定你想要移动这个页面至'%(title)s'吗?" + +#: .\templates\wagtailadmin\pages\confirm_move.html:13 +#, python-format +msgid "" +"Are you sure you want to move this page and all of its children into " +"'%(title)s'?" +msgstr "你确定你要移动这页和其所有子页面至'%(title)s'吗?" + +#: .\templates\wagtailadmin\pages\confirm_move.html:18 +msgid "Yes, move this page" +msgstr "是的,移动这页" + +#: .\templates\wagtailadmin\pages\confirm_unpublish.html:3 +#, python-format +msgid "Unpublish %(title)s" +msgstr "停止发布%(title)s" + +#: .\templates\wagtailadmin\pages\confirm_unpublish.html:6 +#: .\templates\wagtailadmin\pages\edit.html:33 +#: .\templates\wagtailadmin\pages\list.html:71 +#: .\templates\wagtailadmin\pages\list.html:191 +msgid "Unpublish" +msgstr "停止发布" + +#: .\templates\wagtailadmin\pages\confirm_unpublish.html:10 +msgid "Are you sure you want to unpublish this page?" +msgstr "你确定你想停止发布这页吗?" + +#: .\templates\wagtailadmin\pages\confirm_unpublish.html:13 +msgid "Yes, unpublish it" +msgstr "是的,停止发布" + +#: .\templates\wagtailadmin\pages\content_type_use.html:7 +msgid "Pages using" +msgstr "页面在用" + +#: .\templates\wagtailadmin\pages\create.html:5 +#, python-format +msgid "New %(page_type)s" +msgstr "新%(page_type)s类" + +#: .\templates\wagtailadmin\pages\create.html:9 +msgid "New" +msgstr "新" + +#: .\templates\wagtailadmin\pages\create.html:21 +msgid "Save as draft" +msgstr "保存为草稿" + +#: .\templates\wagtailadmin\pages\create.html:26 +#: .\templates\wagtailadmin\pages\edit.html:39 +msgid "Publish" +msgstr "发布" + +#: .\templates\wagtailadmin\pages\create.html:28 +#: .\templates\wagtailadmin\pages\edit.html:41 +msgid "Submit for moderation" +msgstr "提交审核" + +#: .\templates\wagtailadmin\pages\edit.html:5 +#, python-format +msgid "Editing %(title)s" +msgstr "编辑%(title)s" + +#: .\templates\wagtailadmin\pages\edit.html:12 +#, python-format +msgid "Editing %(title)s" +msgstr "编辑%(title)s" + +#: .\templates\wagtailadmin\pages\edit.html:15 +msgid "Status:" +msgstr "状态:" + +#: .\templates\wagtailadmin\pages\edit.html:29 +msgid "Save draft" +msgstr "保存草稿" + +#: .\templates\wagtailadmin\pages\edit.html:52 +#, python-format +msgid "Last modified: %(last_mod)s" +msgstr "上一次编辑:%(last_mod)s" + +#: .\templates\wagtailadmin\pages\edit.html:54 +#, python-format +msgid "by %(modified_by)s" +msgstr "作者%(modified_by)s" + +#: .\templates\wagtailadmin\pages\index.html:4 +#, python-format +msgid "Exploring %(title)s" +msgstr "浏览%(title)s" + +#: .\templates\wagtailadmin\pages\list.html:53 +#: .\templates\wagtailadmin\pages\list.html:194 +msgid "Add child page" +msgstr "添加子页面" + +#: .\templates\wagtailadmin\pages\list.html:94 +msgid "Disable ordering of child pages" +msgstr "禁止自页面的顺序" + +#: .\templates\wagtailadmin\pages\list.html:94 +#: .\templates\wagtailadmin\pages\list.html:96 +msgid "Order" +msgstr "顺序" + +#: .\templates\wagtailadmin\pages\list.html:96 +msgid "Enable ordering of child pages" +msgstr "开启子页面顺序" + +#: .\templates\wagtailadmin\pages\list.html:149 +msgid "Drag" +msgstr "拖动" + +#: .\templates\wagtailadmin\pages\list.html:220 +#: .\templates\wagtailadmin\pages\list.html:224 +#, python-format +msgid "Explorer subpages of '%(title)s'" +msgstr "浏览 '%(title)s' 的子页面" + +#: .\templates\wagtailadmin\pages\list.html:220 +#: .\templates\wagtailadmin\pages\list.html:224 +#: .\templates\wagtailadmin\pages\list.html:228 +msgid "Explore" +msgstr "浏览" + +#: .\templates\wagtailadmin\pages\list.html:228 +#, python-format +msgid "Explorer child pages of '%(title)s'" +msgstr "浏览 '%(title)s' 的子页面" + +#: .\templates\wagtailadmin\pages\list.html:230 +#, python-format +msgid "Add a child page to '%(title)s'" +msgstr "添加子页面至'%(title)s'" + +#: .\templates\wagtailadmin\pages\list.html:230 +msgid "Add subpage" +msgstr "添加子页面" + +#: .\templates\wagtailadmin\pages\list.html:239 +msgid "No pages have been created." +msgstr "没有已保存的页面" + +#: .\templates\wagtailadmin\pages\list.html:239 +#, python-format +msgid "Why not add one?" +msgstr "为什么不添加一页?" + +#: .\templates\wagtailadmin\pages\move_choose_destination.html:3 +#, python-format +msgid "Select a new parent page for %(title)s" +msgstr "为%(title)s选择一个新的根页面" + +#: .\templates\wagtailadmin\pages\move_choose_destination.html:7 +#, python-format +msgid "Select a new parent page for %(title)s" +msgstr "为%(title)s选择一个新的根页面" + +#: .\templates\wagtailadmin\pages\search_results.html:6 +#, python-format +msgid "" +"\n" +" There is one match\n" +" " +msgid_plural "" +"\n" +" There are %(counter)s matches\n" +" " +msgstr[0] "" + +#: .\templates\wagtailadmin\pages\search_results.html:17 +#, python-format +msgid "" +"\n" +" Page %(page_number)s of %(num_pages)s.\n" +" " +msgstr "\n 第 %(page_number)s / %(num_pages)s页.\n " + +#: .\templates\wagtailadmin\pages\search_results.html:24 +#: .\templates\wagtailadmin\pages\search_results.html:26 +#: .\templates\wagtailadmin\shared\pagination_nav.html:8 +#: .\templates\wagtailadmin\shared\pagination_nav.html:10 +#: .\templates\wagtailadmin\shared\pagination_nav.html:14 +msgid "Previous" +msgstr "向前" + +#: .\templates\wagtailadmin\pages\search_results.html:33 +#: .\templates\wagtailadmin\pages\search_results.html:35 +#: .\templates\wagtailadmin\shared\pagination_nav.html:21 +#: .\templates\wagtailadmin\shared\pagination_nav.html:23 +#: .\templates\wagtailadmin\shared\pagination_nav.html:25 +msgid "Next" +msgstr "往后" + +#: .\templates\wagtailadmin\pages\search_results.html:43 +#, python-format +msgid "Sorry, no pages match \"%(query_string)s\"" +msgstr "" + +#: .\templates\wagtailadmin\pages\search_results.html:45 +msgid "Enter a search term above" +msgstr "请在上面输入搜索词" + +#: .\templates\wagtailadmin\pages\select_location.html:3 +#, python-format +msgid "Where do you want to create a %(page_type)s" +msgstr "你想在哪创建 %(page_type)s" + +#: .\templates\wagtailadmin\pages\select_location.html:5 +msgid "Where do you want to create this" +msgstr "你想在哪创建这个" + +#: .\templates\wagtailadmin\pages\select_type.html:3 +#: .\templates\wagtailadmin\pages\select_type.html:6 +msgid "Create a new page" +msgstr "创建一个新页面" + +#: .\templates\wagtailadmin\pages\select_type.html:10 +msgid "" +"Your new page will be saved in the top level of your website. You " +"can move it after saving." +msgstr "你的新页面将会保存到网站的顶级 你 在保存后可以移动." + +#: .\templates\wagtailadmin\shared\main_nav.html:15 +msgid "Account settings" +msgstr "账号设置" + +#: .\templates\wagtailadmin\shared\main_nav.html:16 +msgid "Log out" +msgstr "登出" + +#: .\templates\wagtailadmin\shared\main_nav.html:20 +msgid "More" +msgstr "更多" + +#: .\templates\wagtailadmin\shared\main_nav.html:22 +msgid "Redirects" +msgstr "转向" + +#: .\templates\wagtailadmin\shared\main_nav.html:23 +msgid "Editors Picks" +msgstr "编辑手摘" + +#: .\templates\wagtailadmin\shared\pagination_nav.html:3 +#, python-format +msgid "Page %(page_num)s of %(total_pages)s." +msgstr "第%(page_num)s页 共%(total_pages)s页" + +#: .\templatetags\wagtailadmin_nav.py:52 +msgid "Images" +msgstr "图像" + +#: .\templatetags\wagtailadmin_nav.py:56 +msgid "Documents" +msgstr "文件" + +#: .\templatetags\wagtailadmin_nav.py:61 +msgid "Snippets" +msgstr "片段" + +#: .\templatetags\wagtailadmin_nav.py:66 +msgid "Users" +msgstr "使用者" + +#: .\views\account.py:26 +msgid "Your password has been changed successfully!" +msgstr "您的密码已经更改成功。" + +#: .\views\pages.py:99 +msgid "Sorry, you do not have access to create a page of type '{0}'." +msgstr "对不起,你没有创建'{0}'类型页面的权限。" + +#: .\views\pages.py:103 +msgid "" +"Pages of this type can only be created as children of '{0}'. This " +"new page will be saved there." +msgstr "这一类的页面只能创建为'{0}'的子页面。这一页将会保存在那。" + +#: .\views\pages.py:166 +msgid "This slug is already in use" +msgstr "这个唯一的地址已被占用" + +#: .\views\pages.py:187 .\views\pages.py:254 .\views\pages.py:589 +msgid "Page '{0}' published." +msgstr "第 '{0}' 页已发布。" + +#: .\views\pages.py:189 .\views\pages.py:256 +msgid "Page '{0}' submitted for moderation." +msgstr "第 '{0}' 页已提交审核。" + +#: .\views\pages.py:192 +msgid "Page '{0}' created." +msgstr "第 '{0}' 页已创建。" + +#: .\views\pages.py:201 +msgid "The page could not be created due to errors." +msgstr "这一页因有错误发生而无法创建。" + +#: .\views\pages.py:259 +msgid "Page '{0}' updated." +msgstr "第 '{0}' 页已更新" + +#: .\views\pages.py:268 +msgid "The page could not be saved due to validation errors" +msgstr "这页无法保存,因为页面发生验证错误" + +#: .\views\pages.py:280 +msgid "This page is currently awaiting moderation" +msgstr "这页正在等待审核" + +#: .\views\pages.py:298 +msgid "Page '{0}' deleted." +msgstr "第 '{0}' 页已删除" + +#: .\views\pages.py:428 +msgid "Page '{0}' unpublished." +msgstr "第 '{0}' 页已停止发布" + +#: .\views\pages.py:479 +msgid "Page '{0}' moved." +msgstr "第 '{0}' 页已移动。" + +#: .\views\pages.py:584 .\views\pages.py:602 .\views\pages.py:621 +msgid "The page '{0}' is not currently awaiting moderation." +msgstr "第 '{0}' 页当前不需要等待审核。" + +#: .\views\pages.py:608 +msgid "Page '{0}' rejected for publication." +msgstr "第 '{0}' 页已被拒绝发布。" From 3b20732ded30ebd094b4a1c65de808d5cc54e3ce Mon Sep 17 00:00:00 2001 From: dv Date: Thu, 1 May 2014 12:26:43 +0800 Subject: [PATCH 02/57] add more zh_TW translation --- .../locale/zh_TW/LC_MESSAGES/django.mo | Bin 12227 -> 12236 bytes .../locale/zh_TW/LC_MESSAGES/django.po | 52 +++++++++--------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.mo b/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.mo index c5459c29eea40694e527718aec301ee523bebc57..dd726e6378a82ea6deb9cfa0008e003eb7df4f4c 100644 GIT binary patch delta 1880 zcmZY9e@xV69Ki8M7!-o#v-h=oA3bMk8fZ;_Tk+a)h^;u`ZrPHD+`t4qjvE1 zB-Z02ID%X7JCywYXmh>FuQu`^->cGA;Trn2+N0Vglma^NA&j6T`bv-gjQ7&Ng)%R@ zNU0Lsj5%11QedsN4rL+F7x~?RV?2<+6M90A_MCPYrLYSqfwNeEH&6;$(&M*K3d!`j z3tEpd|6$yQdr-!kPzvhu>xO}wc`&HGjuQA2$_swORrnW5U{9U!vRv6YEiKj1+VTH{i=CXW53b;t)z95tO(&ti_6<|6m!{dl!w*^g#9l?h;m^1l)&wl#egD)_ak6skgKf+MC+Hv7GTjzGQw4%97ti z?uCk?Ed3kYi+`4Ly=BF_A9R11^(d9Ut!=|R`duj3azOW^m_t9I`!`T_>}%YPOX$H( zR3Z7Fz{ju-B~Ms8QA9J;aeNLx$H&oA;m$jR@(g8ShM;kH|iyt1%aXMnhS?ky%>3`nC;L z>46tY3p1^mPNSprRbP7dJ&ng3ni^hjIIi5&aJPq8w}9BjvOq?m+cx9fEG5}~?e|0% z1z5rE3wUUyZ=<|rp_ z&X3-9%AA&a6#u1g58Vny&AD-XX)X@RVJ*8H&fv;cw*YIn&zRhLvVt9rcPCrstzq_i iz#h8BO(8j@r(Zqh%wBaa4>;3fPB>^8V@7SoYySfAoE>2R delta 1886 zcmZwHeN5DK9Ki9fpcMH;rj|*>WAYRyXRpmKGo+#Mds!Fk|xt$%9vk8N&kwfTFv+t}RdkH&w!Km5M%N42?o{k{*M&-e3v zz@KVw)zl4(Ljvlvg3++XeJR1v? zdIF0v6Az#iSfhO#Wh3jhO8*Koku*)cc^O%jdPzqVl$RIv3fqn{uL9-DcI)xO z+B)s~+GAQ*BOh4=oIpv?rS)Sv?I1pcmr*Ldj&f2z>h>R4Oxwn7n8mqo#Zr{^UhSL6 z?Wj*tHrkJz;1Lz$LjrE29N7ZCh4=Gfq@Z{4QEWiD%TAOXpG7&LizsokC~xCeloMD@ zRT)^|P2E@El1$a~NaPzRk?*1OH|m)!y8jfCL=ECDyn!3=Zyh`N z{3u($jtB5}l)I`d=b7`jr}mXQm4Bf92&ItYC_8J_Z9ht(LEXNBa$@sXg|{#lGpRxr zD8*;-C6qj0XnRo#3-04XD*G9wkOdsY4HeFngz+Hl8~7YPTl-*l~~P=}Ebp%#MiF9AwD$O_}4} zspgO!nlNJHDmnSB>6wo1&rPg4Jldp;`Hf8#g@?8+)ve6= z{$wa(%(mUTHlmDJoCMyrMcHfHT2n1S9k{coEG^L&tu5M>mNVMqlx=l%o2N#UQy#l_ zPQ^RBBd0t(Z8y)D?QtV^IyHQL<%q1|fHTS2f)nX|ptw4FuY3o7vOvt*QL@A3(4vJOBUy diff --git a/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.po b/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.po index de09aeb0c..3e458eeb2 100644 --- a/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.po +++ b/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: msgid "" msgstr "" @@ -89,117 +89,117 @@ msgstr "登入 Wagtail" #: .\templates\wagtailadmin\login.html:42 msgid "Forgotten it?" -msgstr "忘记了?" +msgstr "忘記了嗎?" #: .\templates\wagtailadmin\account\account.html:4 msgid "Account" -msgstr "账号" +msgstr "帳號" #: .\templates\wagtailadmin\account\account.html:11 msgid "Set gravatar" -msgstr "设置gravatar" +msgstr "設定 gravatar" #: .\templates\wagtailadmin\account\account.html:15 msgid "" "Your avatar image is provided by Gravatar and is connected to your email " "address. With a Gravatar account you can set an avatar for any number of " "other email addresses you use." -msgstr "您的头像图片是由Gravatar提供的,并且关联了您的电子邮件地址。一个Gravatar账号可以设置多个电子邮件地址的头像图片。" +msgstr "您的頭像是由 Gravatar 所提供,並且已經聯結你的電子信箱。一個 Gravatar 帳號可以設定多個電子信箱的頭像圖片。" #: .\templates\wagtailadmin\account\account.html:23 #: .\templates\wagtailadmin\account\change_password.html:4 msgid "Change password" -msgstr "修改密码" +msgstr "修改密碼" #: .\templates\wagtailadmin\account\account.html:27 msgid "Change the password you use to log in." -msgstr "修改您用于登录的密码。" +msgstr "修改登入用的密碼。" #: .\templates\wagtailadmin\account\change_password.html:16 msgid "Change Password" -msgstr "修改密码" +msgstr "修改密碼" #: .\templates\wagtailadmin\account\change_password.html:19 msgid "" "Your password can't be changed here. Please contact a site administrator." -msgstr "您的密码不能在此更改。请联系网站管理员。" +msgstr "您的密碼不能在這更改。請聯絡網站管理員。" #: .\templates\wagtailadmin\account\password_reset\complete.html:4 #: .\templates\wagtailadmin\account\password_reset\confirm.html:42 #: .\templates\wagtailadmin\account\password_reset\done.html:4 #: .\templates\wagtailadmin\account\password_reset\form.html:37 msgid "Reset password" -msgstr "重置密码" +msgstr "重新設定密碼" #: .\templates\wagtailadmin\account\password_reset\complete.html:15 msgid "Password change successful" -msgstr "密码修改成功" +msgstr "密碼修改成功" #: .\templates\wagtailadmin\account\password_reset\complete.html:16 msgid "Login" -msgstr "登录" +msgstr "登入" #: .\templates\wagtailadmin\account\password_reset\confirm.html:4 #: .\templates\wagtailadmin\account\password_reset\confirm.html:26 msgid "Set your new password" -msgstr "设置你的新密码" +msgstr "設定您的新密碼" #: .\templates\wagtailadmin\account\password_reset\confirm.html:19 msgid "The passwords do not match. Please try again." -msgstr "两个密码不匹配,请重试。" +msgstr "密碼不一致,請再試一次。" #: .\templates\wagtailadmin\account\password_reset\done.html:15 msgid "Check your email" -msgstr "检查您的电子邮件" +msgstr "請檢查您的電子信箱" #: .\templates\wagtailadmin\account\password_reset\done.html:16 msgid "A link to reset your password has been emailed to you." -msgstr "一个用于重置密码的链接已经发送到您的电子邮箱中" +msgstr "一個重新設定密碼連結已經寄到您的電子信箱了" #: .\templates\wagtailadmin\account\password_reset\email.txt:2 msgid "Please follow the link below to reset your password" -msgstr "请点击下面的链接来重置您的密码" +msgstr "請點擊下面的連結來重新設定您的密碼" #: .\templates\wagtailadmin\account\password_reset\email_subject.txt:2 msgid "Password reset" -msgstr "密码已重置" +msgstr "密碼已經重新設定" #: .\templates\wagtailadmin\account\password_reset\form.html:27 msgid "Reset your password" -msgstr "重置您的密码" +msgstr "重新設定您的密碼" #: .\templates\wagtailadmin\chooser\_link_types.html:5 #: .\templates\wagtailadmin\chooser\_link_types.html:7 msgid "Internal link" -msgstr "内部链接" +msgstr "內部連結" #: .\templates\wagtailadmin\chooser\_link_types.html:11 #: .\templates\wagtailadmin\chooser\_link_types.html:13 msgid "External link" -msgstr "外部链接" +msgstr "外部連結" #: .\templates\wagtailadmin\chooser\_link_types.html:17 #: .\templates\wagtailadmin\chooser\_link_types.html:19 msgid "Email link" -msgstr "电子邮件链接" +msgstr "電子信箱連結" #: .\templates\wagtailadmin\chooser\_search_form.html:7 #: .\templates\wagtailadmin\pages\search.html:3 #: .\templates\wagtailadmin\pages\search.html:16 #: .\templatetags\wagtailadmin_nav.py:44 msgid "Search" -msgstr "搜索" +msgstr "搜尋" #: .\templates\wagtailadmin\chooser\_search_results.html:3 #: .\templatetags\wagtailadmin_nav.py:43 msgid "Explorer" -msgstr "浏览" +msgstr "瀏覽" #: .\templates\wagtailadmin\chooser\_search_results.html:5 #: .\templates\wagtailadmin\pages\index.html:15 #: .\templates\wagtailadmin\pages\move_choose_destination.html:10 msgid "Home" -msgstr "主页" +msgstr "首頁" #: .\templates\wagtailadmin\chooser\_search_results.html:13 #, python-format @@ -217,7 +217,7 @@ msgstr[0] "" #: .\templates\wagtailadmin\chooser\search.html:2 #: .\templates\wagtailadmin\edit_handlers\page_chooser_panel.html:13 msgid "Choose a page" -msgstr "选择一个页面" +msgstr "選擇一個頁面" #: .\templates\wagtailadmin\chooser\email_link.html:2 msgid "Add an email link" From b554c1d2a0196be8a85498c1176953250b80d430 Mon Sep 17 00:00:00 2001 From: dv Date: Sat, 3 May 2014 21:33:47 +0800 Subject: [PATCH 03/57] add zh_TW translation for wagtailsearch --- .../locale/zh_TW/LC_MESSAGES/django.mo | Bin 0 -> 3859 bytes .../locale/zh_TW/LC_MESSAGES/django.po | 191 ++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 wagtail/wagtailsearch/locale/zh_TW/LC_MESSAGES/django.mo create mode 100644 wagtail/wagtailsearch/locale/zh_TW/LC_MESSAGES/django.po diff --git a/wagtail/wagtailsearch/locale/zh_TW/LC_MESSAGES/django.mo b/wagtail/wagtailsearch/locale/zh_TW/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..b5c01463c7ac9ae52ad17a20e7a43403d5c541f5 GIT binary patch literal 3859 zcmb7GTWlOx89pK9W}uW(D6~KiCRJ?Vwb!{ov~gV0)QPI%)FewI)JoQ5=XiIL*_q8; zyj@Vy=HlXHZN~}NO;cl{kfw&DwK0ui?6oWL#v@1wo_JwrcJ~4Kg}(8?_s^WY*maON z^6Ymm|M{=qImiEa^r0z+wgcbS@bzqCY%lPYkKqR`x*dIBH}F5e3E&RM6dq#i3m7ka zoUtzf{|I~x_;=tD;J<*M0Pe-lBfuWu!@z#vCxNd3X}=1595@X8CU8RH0+96n1^8KD z1^7AOhrnszb}0EY@H&w6-NMf);9Vfud;C+3!9~^vB)=kZ{45YE*byM7Wv{xu-QaREsFO##0Syd&{XK>V??#D7cNh9sTC{KG(6zanuK zXwZHj`SS#VCHuR9WH%b;-t_o=k6_syU`*^Nf}_ZFAbH@U&127#rf2NSNug zFjUP*ayugu+K`su86_!f?xYllr?q6t;fCpO(@H9amQZv($FWK96qdM~;hMp1p;(C& zwArri*qywuGr3W9&U7uFv9z>e<+y4ZildoEV23*<9CB@8NiF0_R&!FA)rD=7tu$m2 zX`1WWX~A22M7lSr4MVV}3*FYvo~}&q*1;oRy!CkK9cgH@+q*I;OR+^OAJT-b@{>Y0 zvpntE4lEgtf@mCU8gg}=D~8I&t4hMD1vq3{Je$%GDguI+c8c83Smv;%ibljjt)-%a zle3zU&|OM#;4jqXkXIY&)^$wUT|xB1vP`R!$4#CRdZr_=kWdVsNSUS$hb%K)bAuw0 z^+_qi0x<|A)6BTK0{xB_+JukM%^SKT@KEV)GSlB;b^fwI*kqT z$ZfV`!FNhdaIQP~L4()18j>qmpwn-OGp=SK%j9rSxtfK6;P67pNzvG?YIa6fazgDu z(RDSUSZa8{kG>eE8kkv%wBH0nR5NRYJvYOSnj4F3^9GA*3F0SGx!~CMC_H6}p#!Z? zw`G+i&W9cbHYf`mq-9W1)j`+N+wIm~bm!tRhnV*{3XN+g`f^J?TJoHtx)F@7RUQp+)sF)b(3ZznZ1 z@~oS*BXKjvTLxZ?M-CAQAsl%QOpEbd(e6Ew=aLEV}F4(OuCf1S7}9utrL^ zkn4_hLk_Lw`*1B1w{V~93hwzB&#J?FzPoo{iucrd-%F-ZwoY86y%0B&F3xZyE|fI< z>3_bzui<=mXSC%IZb4x{XD$Qh9Pz5t1(s>Xe%wTgWeexP595a;`xIk{GRvj8{z)a z>IayFc5igSAD=9buhjQE_&q8u6`+>%*OYl5j8t!o!ne}u4R2}8pLr`(U%of#&(1*7 zdvDC2dcQ8eUL2z*#Ty&(3wHyqmR43ut5e?P`O5iKzfi1>&0|;PH?!ote|fTeYZ-e; z`{nu4%G=)BZ29%yRj2dKPEdA!{xfXY=(%@u*1L40IfpEq@~0QDeXE5qwL$V2Y?f~> zd+%NM&;P!1`>Z$m+v=OQ{EKtG;)CQ7UeBJ9rgnX=S;5r+@?mN@{y*tNvT>BjU}g8$>q_Dt8K%;*vM=c337aDo)-7Az{cH zIp5B_wLHjHerLriOof9>a^NpsrIQt~rr8MbrF?F=w34qb7onK{-&cQ_#qi8}S8j$+ zKxodtxQ1#=qXD&9xWGQjM&?~u^xnP3LXt?R9{@RS_WS`NjV;~+o$SiJ`#1>?3O~GL o!v8KG@Fp}AR^G{%X9|41I9gh|\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: .\forms.py:8 +msgid "Search term(s)/phrase" +msgstr "搜尋關鍵字" + +#: .\forms.py:9 +msgid "" +"Enter the full search string to match. An \n" +" exact match is required for your Editors Picks to be \n" +" displayed, wildcards are NOT allowed." +msgstr "" +"請輸入完整的字串來選擇。\n" +" 輸入必須和你的 '編者精選' 完全一樣 \n" +" (不能使用萬用字元)" + +#: .\templates\wagtailsearch\editorspicks\add.html:3 +#: .\templates\wagtailsearch\editorspicks\add.html:5 +msgid "Add editor's pick" +msgstr "增加編者精選" + +#: .\templates\wagtailsearch\editorspicks\add.html:9 +msgid "" +"\n" +"

Editors picks are a means of recommending specific pages that might not organically come high up in search results. E.g recommending your primary donation page to a user searching with a less common term like \"giving\".

\n" +" " +msgstr "\n

編者精選是用於推薦部份在搜尋排名不高的頁面。 例如用關鍵字推薦使用者到捐獻頁面。

\n " + +#: .\templates\wagtailsearch\editorspicks\add.html:12 +msgid "" +"\n" +"

The \"Search term(s)/phrase\" field below must contain the full and exact search for which you wish to provide recommended results, including any misspellings/user error. To help, you can choose from search terms that have been popular with users of your site.

\n" +" " +msgstr "\n

下面的關鍵字必須是你希望推薦結果的完整關鍵字,包括任何可能拼錯的詞。 提示,你可以從熱門的關鍵字選擇。

\n " + +#: .\templates\wagtailsearch\editorspicks\add.html:25 +#: .\templates\wagtailsearch\editorspicks\edit.html:19 +msgid "Save" +msgstr "儲存" + +#: .\templates\wagtailsearch\editorspicks\confirm_delete.html:3 +#, python-format +msgid "Delete %(query)s" +msgstr "刪除 Delete %(query)s" + +#: .\templates\wagtailsearch\editorspicks\confirm_delete.html:5 +#: .\templates\wagtailsearch\editorspicks\edit.html:20 +#: .\templates\wagtailsearch\editorspicks\includes\editorspicks_form.html:6 +msgid "Delete" +msgstr "刪除" + +#: .\templates\wagtailsearch\editorspicks\confirm_delete.html:9 +msgid "" +"Are you sure you want to delete all editors picks for this search term?" +msgstr "你確定想要刪除所有搜尋到的編者精選?" + +#: .\templates\wagtailsearch\editorspicks\confirm_delete.html:12 +msgid "Yes, delete" +msgstr "是的,刪除" + +#: .\templates\wagtailsearch\editorspicks\edit.html:3 +#, python-format +msgid "Editing %(query)s" +msgstr "編輯 %(query)s" + +#: .\templates\wagtailsearch\editorspicks\edit.html:5 +msgid "Editing" +msgstr "編輯" + +#: .\templates\wagtailsearch\editorspicks\index.html:3 +msgid "Search Terms" +msgstr "搜尋關鍵字" + +#: .\templates\wagtailsearch\editorspicks\index.html:17 +msgid "Editor's search picks" +msgstr "編者精選" + +#: .\templates\wagtailsearch\editorspicks\index.html:18 +msgid "Add new editor's pick" +msgstr "增加新的編者精選" + +#: .\templates\wagtailsearch\editorspicks\list.html:8 +msgid "Search term(s)" +msgstr "搜尋關鍵字" + +#: .\templates\wagtailsearch\editorspicks\list.html:9 +msgid "Editors picks" +msgstr "編者精選" + +#: .\templates\wagtailsearch\editorspicks\list.html:10 +#: .\templates\wagtailsearch\queries\chooser\results.html:9 +msgid "Views (past week)" +msgstr "觀看 (上周)" + +#: .\templates\wagtailsearch\editorspicks\list.html:17 +msgid "Edit this pick" +msgstr "編輯這個精選" + +#: .\templates\wagtailsearch\editorspicks\list.html:23 +msgid "None" +msgstr "沒有" + +#: .\templates\wagtailsearch\editorspicks\results.html:5 +#, python-format +msgid "" +"\n" +" There is one match\n" +" " +msgid_plural "" +"\n" +" There are %(counter)s matches\n" +" " +msgstr[0] "\n 有一個符合" +msgstr[1] "\n 有 $(counter)s 個符合" + +#: .\templates\wagtailsearch\editorspicks\results.html:18 +#, python-format +msgid "Sorry, no editor's picks match \"%(query_string)s\"" +msgstr "對不起,沒有任何編者精選符合 \"%(query_string)s\"" + +#: .\templates\wagtailsearch\editorspicks\results.html:21 +#, python-format +msgid "" +"No editor's picks have been created. Why not add one?" +msgstr "沒有任何編者精選。 為什麼不 建立一個呢?" + +#: .\templates\wagtailsearch\editorspicks\includes\editorspicks_form.html:4 +msgid "Move up" +msgstr "往上移動" + +#: .\templates\wagtailsearch\editorspicks\includes\editorspicks_form.html:5 +msgid "Move down" +msgstr "往下移動" + +#: .\templates\wagtailsearch\editorspicks\includes\editorspicks_form.html:10 +msgid "Editors pick" +msgstr "編者精選" + +#: .\templates\wagtailsearch\editorspicks\includes\editorspicks_formset.html:14 +msgid "Add recommended page" +msgstr "增加推薦頁面" + +#: .\templates\wagtailsearch\queries\chooser\chooser.html:2 +msgid "Popular search terms" +msgstr "熱門的關鍵字" + +#: .\templates\wagtailsearch\queries\chooser\chooser.html:10 +msgid "Search" +msgstr "搜尋" + +#: .\templates\wagtailsearch\queries\chooser\results.html:8 +msgid "Terms" +msgstr "關鍵字" + +#: .\templates\wagtailsearch\queries\chooser\results.html:23 +msgid "No results found" +msgstr "沒有找到任何結果" + +#: .\views\editorspicks.py:41 +msgid "Search editor's picks" +msgstr "搜尋編者精選" + +#: .\views\editorspicks.py:75 +msgid "Editor's picks for '{0}' created." +msgstr "編者精選'{0}'已建立。" + +#: .\views\editorspicks.py:103 +msgid "Editor's picks for '{0}' updated." +msgstr "編者精選'{0}'已更新。" + +#: .\views\editorspicks.py:122 +msgid "Editor's picks deleted." +msgstr "編者精選已刪除" From 39afed0e2805e10e2746303867f5a472802cb70d Mon Sep 17 00:00:00 2001 From: dv Date: Sat, 3 May 2014 22:28:11 +0800 Subject: [PATCH 04/57] add more zh_TW translation for wagtailadmin --- .../locale/zh_TW/LC_MESSAGES/django.mo | Bin 12236 -> 13960 bytes .../locale/zh_TW/LC_MESSAGES/django.po | 240 +++++++++--------- 2 files changed, 123 insertions(+), 117 deletions(-) diff --git a/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.mo b/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.mo index dd726e6378a82ea6deb9cfa0008e003eb7df4f4c..b7bddb8ff7290512d555145b3db2f3252b5a09d6 100644 GIT binary patch literal 13960 zcmb`M3v^t?d4PxF5HJA(BqYtFxi}c(V#%_B0K$eCY$t9p7%XtzLY=GKD`{c1tL)vi ztOSB=b9!*Zt^dwE9yQ@ue4$V0|X?uE3+wY&5 zy?a-ZZA^NPN8iredHnOw|Nk>{{qyU_Y*Re@NuMB1d!JIjfKQC&56@4oQtBD_Q+OCY zezj67;h1ZbdLDMbcKE>$Dm4>shF^d`hEKpduT|isg{SbZ%4nqE^G1n>e zA$S912z4vG64pW)e>Rl%--Le(--eIC-^07%=dV|)3NC|)qit455Q;PAH%g!hBKi9o1oNN1Ev3$EZ=}4-$^L)oPn|)-?s0+4?j-+7f{yazagfh zF8zpUcZKEEme)g(@1s!WKLJX+DezKwH^K z@oV7(=-T`mo9~6UQ~nb;310O{ldpwUm?Y2--P0~6EJ3mP>(`c*A$fX&O*^w z8x;L4hce&oQ0nc6qNjsU>K%u-z_ajHI0PN|Ar?vO{|+eqcu?%44a&G3kgDo6oBs~% zCI2gk39BuRQgL_?&Vkq5Xy&&N){k-Q6hpKKLw@bvX@X-rs^E=l7x5*}qv{!D2{!8)rEcCduCqFM~Z$ z+MR&2;g6uK(JkQzuHYj@QhBdIyzAr)<=YK6P!bLL;`2K2B zek~NaZi3QoI+S>|5X$`5Ly`B8 z`uJqThozl7e@)8hU*?a<-C*;mUq27>cL`|~=^hel*7{irMc>zxI{Cd>p=2~ums7$XRE~9qX za={+^`ynVgy^*w%)IxfJ^k<~f({6vvvD^orA-zo6L|R6QK8wk`NXn7sleUp|k>t6b z^cSRcq)SOFNM9m}9g9sgkz`F-I&BM&!7q};@5P7Y`Lsd!cQ3zYknSZtLXz0oNU9^r z(@YY3d`>bvV)OER$Utp@`$;oNe@WU&+Dek=E2Ni5e@-Git5%Xc?<0L)|1x(F`MJR6 zcf&6GI|(1Rza=)w(@C1Ff0;k?z$DVsB=J`{D?Uk*7}`OaNLo*NiX{Fm&wZpX>tDn> z7$+?vwb`-{!q1ZKBzdH(Nb-Dv^a;|A~~g zbsr4enn)%cH|eLHxR>;@o{=O?$9}H9#clMe|DfK+-xBxyn3syXsq7*xsE8Tq-hVg! zPxD*c)VYza#1`T^C$Y#ChJ0HW;&K@_EOmjF-I!x-E>i@xC`}>Xhu5`LFP#Q zqNEtLhl>+JRwyFFyo(iKl=c@AK*qr8q~)SiuDM=YUb=xIa*J$-m8)8*%6S=Yal&g& zq#B(GtZ5>f^d|ZfCW*l{C$d>D?$o!@TbNx`--gkoQx#?D)WnGCR1R<+uNtl5g}g}3 zaFU7C(@r++WIW%?I&JA(#%XbVzcrnSJ58?d)O%ja@tWO466vW&jcPR`rVYMCho)I3 z?W-B_xZ^sprbIGMH)xX<5lxu)wm&^|Sh55^Pr1o*VYw4s$NH?Ak<=BliN#*BO{8&R zZpz7}T5|Qtgx}<3n>;;owNuwb5XgAV>BXKO7CQ}@bhD!?#~fKJ$4$k!i_u z?Tnn;=q6H5(q&ZU-O`ewJ2itKB18K*`=ga0Aak{mCM!eB{O>z=Rgnv^Y(*`GOTfb1 z5?SA~Vjl!+Ph*EOCUiM_V5#g(; z=Ea^CZDouZQIJkk#nlQ5bIdgBHJ7t#`pt}5CVDN^Yi&xzSo5|PqI-j}I7XTf$BdrV zQp7SIONSIm&&{CKbRtIMbaOLKrwufgPBkPNa~U_ANT<{Tx;nC@unaR$sYKUKM5@>V zeAha~y9vO}rMPyia{TjVO8#^wpdcvSp2?=7=i7nDwCRXW9Sb ziH3w1uVo>U6fB}(qOTsr7t*<`5DS{?rE+Sn%xkXbP5wmIO=sijR_e)%T#I_hYn4PD zF}X!z?ezJOwSA^8p|(tqvh5!*8x|@3)wc(DfW`$0U$Uq`4h^Bpo2-^EESoQeiC*Iww;`)^&i>Q^M9nY95q>A>HH^NZ zBNL>>bjp$Kyw%PT?&c$BW5!+VX59?q*prS~OS1@Sexgyf+Y%*CEpQvN1V)OuKKQxj zW;fHO=BE-ZEgnjkpU!03CON5+59(WvHkxtcZ~0=*%d{=>vl7-P`s1_(m0F-7IklwH z+0l<(a&tmuVJvi9bKa8cRI{7HY4t(Ur32X{iAam(bYkU^-s5S+%9^M^V;gpjYulYy z3|z1MFe_K{vu>6}H>g$f_1SfpU#dEL%yO8jL=mP~J}#cio8Mcj>WXG|uZ@i6nnPLq zT~@nLccplBf$mDxBHfu-$r_33W4VmjFY#rRcob>GL7KC&w1~u^cupT)yiA5I`dpPw z+_6=)`|7yrm{wMNW81i&F^Fclh*vu$*UuoGoNr|a zto^)NG~)Ql90yIpev*?~yp6Ht1gh%fxTEUWE7fDA%R%{9B$|Y8+3VF~_>!+4mwSPU zQu=3-%Z6IuC1V@}BrM={bl?*d7RfPXqF)LW&I5Djs|EVY2MQNQEL{vj*Q?yb&sSHr zDmrV^#xc!xnlfI)bli<|l)j5D%4L$c-M!@H)5f&P?!EV^g`Pi&QwS>7JDup!l!cq8 zOmm?LK#soe$ZWK}Mef@0U5mNP>dB7sTHl>UHsxrjW2~dU0LZ$?jVTc~5$kg{0_)q3 zEN?oMGKT}Ss*S3`1go6|iEI<`s@%>7LQ$=3;IjPyJEm+CZVH9zySoH96Cf)(eY*BR6F#ph1AO- zSIGuBI^(u%33lw#HYxQcm=K_k0^GgjI8ky`@g7(2jM6h6+MK{6vz(FA#C<)Bu&40S zZVnZ3_N~&XBH4DMsa!f>>vafQ#uIT7;+!!;f4eB1aP_APjtFTv2vp69S3QpB;P161 zUl{wS*OJa;tLFNRiFnohxkkULE?w)4o%e8E)dO;=qH>kolWLu*HB)Y{s=2Ld%I(h7 z+iGj3-dZ!YriO}DkMcQ1I<2U8M^()fXUf#tn!9hU;TbCj@2a|toASA(r!%!qYkcwT zciwSVlQXUK>$8n=zp2K5@1=UGF^5}J)p>3+^30txcUD>WDb+P&A26}1N`gl%H=HHe z$poiF>K+bV(^@x|wO_5Ke=crct zHd}1pF?e!!zH51~`e1R#e$#JocvErD(&9_|e%-#TRI$X$(MqMmx*-mZ@);CSF0SYB z)Hcdz(0u2r!GRMO_4%>#JL-GrVEFgTpsTa6X4OT>@c+<-gx$y|P_t4OCB%E_p>XIB zt12zaA3-Nm68Q#-BpA$jBq{FMG<4u}^jbbicFfXeQ1jh0=<2R0lnL6LGLR56`tRlKejD6 z^RgLh=(YAjSI0Z2)`h(l-s&DY)f1dq7pz>LKeU$)QNJp-?<_9epr}>Y*N?u24lFg1 zg9yM-!S)UBoZ4OSy71aS(6OyN`U~rV6({m*+F7!5Daje$O@8??1{&7WFwKtEXjEO4 zIzM|PzxAY9Z#6hFQ`j*Ota!DsRo30qlKBt4(UCv6FTeZMkp`iR{_WE0_*q%Bw6C~l zg)Kq{g9Dwkh!kx+z*>ybJm_1O@7fg%^cUXf5F^xG7x%s#yxbuo<@;6;xy|5;=0mFw znJOiN)D2C)*tvP9a5I+7bXqYchJ^pw3zbt?)?eJaZj@@}ubTPoujadO0=QDs7xGI`Hs%~u4BqrorMV4-eCoTIVWub_CmYhhkZoSmmKpeJp=*dslJ&@!;@wS$I=qEhfy5G=#x3D@TTuatEe? z4IPE{jf6y1foQyN#QI9xv8{HY_u=ZP$~bcN#i8yO30pY8eX4k%6UAZ%vW2Pq#uu2a zwF4deRIuW;ats>mTgyuc13D_ab82VBmrU`MRsG7ij97Tkc|_%ReKpv>QyH(dh^$+1 zrhTxl!@kv-wKjv1VimpA)!U7Hj$jK2RX&Ysh^$+{ZSz(9FrX0_ESIOy7uY$ysWv>*Mt(ED9<5D_!`YeG|RW4|BaN?F2 zSn%e4W&FzoJ{9$Ec~=~GIlqN|J5YekQyca$@3h{iM=1Aa zJOK;KZ(B{v{ElVC&Mizy&M(>o*R03dWs6k^6!dNgHf<(^$!bag+K(P5DvBxwwAQ<< ze`x)hLibr^@-~y-)D`r0D1&k&A|#jH$T4x>%G=p1!uG5;x>r&&JVRIfN6&ei8PUrh zMor$x&CF~7w9al&y56b6iKB%#cH}p|$bPMeEcqkHRnWVBuy6g)@wYf$7{47H7#KXg z%}8l3G0r%-I}iUrs;|)FDmz%#EuCShUEN}Y5oJd;%TU3tJt)8y>VsPT#h${}H_g^N zc&b0&wLaL<%~7OqWN%^9N-^4~sGM(xI>r?*vUye@2OT8r$)?RSa;=$72&b4>qxLh zETGucE~mIi7_u`lN@TroxZ=8=p@aK}+Sl0wY8Z)`OGUlcw+|g2QCo*0y^z|W85GYL zTJ=@Tfq1}4cIfp3l(3OWrTm&R)Zlb)^%OadTgk8(V?a)L-Vr12T3+1SQ`p~+x#T-f zg&PLW$F3P1IVoGy$v1+vuTwJAy*9tJr##b9BC%YIyLy9{+UW@;+Gv^Y-oepJ89P(a zqijW{91ALnIfF~g^flPSEllZabbvs&d3?;Se3q1b+u{hzL)pDz)<y#JDs&cJY)s%V2brjYh^r2(WCH#LDjAJND=A|$#XX0E z!@3jNzFdS?#zNs(V(VgEkGe?3*_d2o%+$y!l W+he;9BBML~;OQ=$0#mL0X8C`lgFHO| literal 12236 zcmb`M4RBo5b%1XYOcFyv6DTBU(mY7OI9NY65I`6^VC=*x1_c>h0>nJ+K1mC!U1i^{ zWrdK)Hnt_pwq#^v%NDU@j4{TRY{0fG+19j8GM(vkpp!K1q)C|$`}QZDmb9H|(>9ao zckaFWC(91W^o{O*@7{NR&pqed^Pc|kcaW( z4!8kU!LyJ*_0N|73vVEQ8H38W3;1CwY6+w(^)+}Ue8MsbYsh!O%i%cuB>VxCdA<$# zQ~$=#r{Mc3l%;mh$?2S0xdUxYH> zKZmp7Tekckpv>!kptQT{<7VEUgR-6mDDrBCAA)iCIk*-&a0p7hvrzi~8_Tz$%xFEWZq8e)mC<)1y$@dGG_U6|w~NO(^X* zKRS19ZJPbmGVt4%*2gffq-p~(9S zQ1=na@|@4e((o<2?gK5068-ROg_K`(wzKsGr&A??Rc!ui@ix7K>j7Ls0rZ z45i(1DE*v~t=|l>J-@Wk1`X?DHBZa(WtyTsA^k=OC1N2cgL42$XuK;EnLl;7#xs(1BOex!CJ% zQ2J?xq8Cp?{?s;p#ExFE`M-q6$fqHqQqSYW!te-O4nOu8v%W`R9r-ROa{de0_dcb5 z0+*6+Mk!Xoqi`{tZul-Q^dCNZkITXG4C6s!X z;w(fTJ_|+u%b?7!-f|U`b$r9-V^G?qY<|1t^Oi$U=Jg_!b|;~nA3uaLk9X|zUqYG3 z2R?7s^+_o8Z-upRDU|1Hpv-5hWj_=<-D5ccrQJ`V^#2PecK2UU+RZ{)g_lE_*OgG} z-2i33Znn=Kw0y+!3Cm{77!*IBg3^AIWk37?`C%w}c>v0I<51)@W%GXzMX%q6n2h?+ z4Ms1ogOb0)vH`L+sujvQ`=H407!*DJYlup#G<*z-vdDZMhnR|b63RYqgtFdVDD&74 zrQIYHfAe=x)_)n3x)grFa=zv5mWwTyLFsP=l>VN8BKHm`<99>pXTX-f02x9Zh2lT{ z)|StnYxeb1Q0mu0@xQl0>1UZOZ-5c7_%v`G zlzkb8E8$9(Nh_7i)6UI zVxWJQ@+*FH5lP1T4rv2vFXjB3(iH5J|2-HBe8$C`oK_ zJ&EP$>j8c{?ESak!}eZegQ&Gm%!gvDK1pPXDe6n)vXS(x$?EfY7x&9;ULZDExMUw% zNpk-5lD3n?HsumsdXnUjHQ?plX{X|_mD0jZ6hrpiOyY4dXy9+iI4awsf{Gpmq_=MzDjB&^^xR~vuzD2PHG{E z?aK8L(p~xv-v|3iUn7YQHj%ze`ZnoLNZlm49wEt@D0+A&=_=Az(tV`D<#KZk$tx7V zwWJj!@fVv(Nm3`NaNSV2vHS#FLb{SPn^a3GzgClpkapU_@4{82-8R1oK12F6sh#vV zNv>}gs017$ts{MqG)R)`Y0}q8-;~U3XWCWoHha$XH@1P*u~ciLmze82@g|DMt(Ibc zu3ufztg@5(gtsQ*wMSyj&YbISOh%GXZ>~RQp5vz)TO-M&7j_yu=&hJt-Pj=`#45_- zvGPIG-A*(Td&)`1orLFmNv9*8N;qw<@3+SjVW-9Qokq`#IbN$9i8287s8Ox%4u#^W zSh7Herb*`ItGmNt$8|z2k!YB1STHThCTpJC{`AnrlC?=M5p$!Z!cr%?4$G1b)!k8D zF&SCoMLT3RPRNZpsaRX8F&gn(oMelqN3M2OwnTiE)f!*p`Nd+VDG_gVbmfpE;&j|t zxY&&sjwGEp60n_-bDP~r%!#^;%DUUy5_G5TPI$VFpRzaYZY(Kl4SP{9$*N^&neO5X zSCx5{D(Y#t(Wq!dBGn22TniqOXq?IsgL_s`G6;}(Wm}8|$ueFqo({EzNGOY%-llGQKh&}IU z^F(l3;}~g97&UrI&mxrY*g9qr_1pwfjYmSBS`u$<#V&O9P(0QYX-*~FWF#I_OLTSS z7DF@4K!p-rJ5pA~7GPf17S+A3-_jU&6JhR>p1M~ngGG5Yqa=}}x;NsxjZx;F2zv=J zY!*?{dtcof52aeYSdzPh+pLzNp8BVxH##dVOS6z#QnJu*b7PB&|)C-d>ZMfrx!*~~La7HgktXwlH>P=i)nVyK6MR)Qz6EUb%M3+EK`P z5sz_rGwq~H>q_6UBO#y+CwOvF#&U_?MZz7Opx zzc1{7-Mf015t3A}{xW2Ite*;nu#l!ywDd?H$f_Q{g|lpuA4nbuj<<$4C*Uxu0rnbrT(`Ar@(C^AJKqJdx;_SBM&7@#M_W6M7*6 zD0()>HDQy(5!>pB_nd@Iyiux{Oo4;SH>WXIe$SfPpHL+FrJy!c|-4(pg zZ|Sa3t*kra`Pd^7eJGU>ZNyv5;9bfZ5f2mcN{ceD5>DwD#7iVNa4%HZcoADw8>9A; zj%j75Z!{HSG78b^CPOXNPQj29%ud2o8G?E1XuWvq+J#`g@#a{>7k8;^QLZ&JTnJj^ zRl&qlEnc(@UxZCye~d+BBu9M;al|?LFiu*|!MyE}QS^x6h~E}S z=sGP4ujww#ji^W;!>dz?C}y{aJUiemtZ^4DR*!i8JYot&tj{fxqbVyMg|f^??Awoi zZIRVzdCR=(iqG22Tccj=43G6I(D_XX^t8uxA`<<`zQ~JDBy2p^m#sh5FDf?E3MIyYFTRn zX%U8@<)WS<5Z@GE;M7LFWYyv{lkqku>hU_M4|^F-FQMIQ6xFD9=v_}zZ-=}QHc23i z*>cp|u?vTu)SF{mfIirHg_hu;V5nj}u0H3aXDqZef<-2Yc;fhdy^3N_#dmKLB7`}G z3Nb>o<62X>5H9O|D7Fko!ZL{q`Uw4%pb)R>j|3d}aXHqjmWQhz#&WRtx`Hjte$Z=+ zCz4ew{N_lw>Yh}yU$rt`=gh8uU}e=3c{ieRmAvlMISXp%-%?e3bJhG?oCP=6)h@WH zc0p||6{{ZP!-aHOQSa8O+WF4>1$DJ|+*HdoTf*q7l?gZI^RgXJ)H&_pHMiV$>+LPh z!ouB`n&oY!8v9*D^;mNX-K<*axvh21l9ot}n8dlUC7EoitEp*kZ?8tMF+bAet(6uv zD6p*2uW74kH>Z0|)b>&Ht(Ka(vsWx%v9z@O`PH?vml$tXCGMw=H=ec08r)kXb|=B2 zn?PyrdT8acs@qHTWWXjbQMEJ{;(Z|2T<6^07)ciATIYPLWp;g(m(6I^GCZqa=fv7{ z*1v21osPM^tM<;>l^=fOLsIt0kwPe0{CHGDN!hof{K$!meLl+Xe>V4WSNYeNdE)&F zACJt}qG0GyMWK8yax%Sr>4^iSzEyg>GwAHeZ{C&}IF>tfG#K3zjBU#9Ka=l#F?*sf zIQ3fgWPdRBY|wQqv;I(a&$Icxlflux^wdap^muw=lM2RP&kgQVxi=05y{B@c=dx!< zRp!)Wuw|HPEF=HI{@mu*%U|uxQ^rk?AI|PPA=TE8rYBG4`_E;zzhoPm$H9St{Dwmn z4~o4`A4R3l4l`cRJC>e&Dd-)@oa_pEcLd`bGDiSo5_8CZ&rg%=kvO!3-&So$ET1*V8b1txR(>0NQRED$E4Als~f% zP$TTe2DeUnd?LSp_YBoaABr-&UdjyZV;Io}i(&_b;_Sh7>_=|1-9Wv7iD05vWd=55 z1S-=rfTk#;ffmfKxZ}2{)UT;|fj1`eFw@humtV?Q?ApFqy)Z@Bl3;J_YbjMt*1SSsk- zksj}{PjzOC&7h-b#j%R;6t!2uIW}#(%Dgrr9^}+(>8Tfjqq~cypzJPk%-E*-lM!0& z1RIYdl=81elqxxo%!?8^`ZG!{7Ipp;t=iLz&3tEUpgr(RPjdTT&GbB%oqVC>T&H(y z&Z=N^Br`ldQy1l~?YyZXb&;Q#&ct40(dcycXm@aKqv=vV8}CG-MbQPlhdCGuMm|yb z8eXn}Oh+4Kr$~$g<;)(l2@H{6|DsH`G~~`hs$vVB@)7YfL>*u@1kX9aD9HD zUzvDAR5j?{rp%71+}R@(;IL#DRr&O+YbYAD1BQpc{67Qu>b8@@;e7}V`ErKcIUoa=hn=w;mqsLmmDioU@J_i z(SEc45@qOk#**;ggN;s6XrPs>qr`qf~|E0p98 zZON<~v#XYM9DQ*{-+DOMIVR4HK8B73FLcr?`x)fb_MYBUa1?QnNGMR~~Y`=+D4iU~)`672GM7d$K>bZj2X4hGs3()Xy9)r7leDXVzigJrC@ernS^8j!xr1Ko7X-4@@T|g zt*j^3C!{!8A_Iu;?5>hpg<9*YwI diff --git a/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.po b/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.po index 3e458eeb2..e6f8e743b 100644 --- a/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.po +++ b/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.po @@ -10,11 +10,11 @@ msgstr "" "POT-Creation-Date: 2014-03-14 23:02+0200\n" "PO-Revision-Date: 2014-05-01 12:09+0000\n" "Last-Translator: wdv4758h \n" -"Language-Team: Chinese (http://www.transifex.com/projects/p/wagtail/language/zh/)\n" +"Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: zh\n" +"Language: zh_TW\n" "Plural-Forms: nplurals=1; plural=0;\n" #: .\edit_handlers.py:81 .\edit_handlers.py:130 .\edit_handlers.py:134 @@ -211,7 +211,8 @@ msgid_plural "" "\n" " There are %(counter)s matches\n" " " -msgstr[0] "" +msgstr[0] "\n 有一個符合" +msgstr[1] "\n 有 $(counter)s 個符合" #: .\templates\wagtailadmin\chooser\browse.html:2 #: .\templates\wagtailadmin\chooser\search.html:2 @@ -221,36 +222,36 @@ msgstr "選擇一個頁面" #: .\templates\wagtailadmin\chooser\email_link.html:2 msgid "Add an email link" -msgstr "添加一个电子邮件链接" +msgstr "增加一個電子信箱" #: .\templates\wagtailadmin\chooser\email_link.html:14 #: .\templates\wagtailadmin\chooser\external_link.html:14 msgid "Insert link" -msgstr "插入一个链接" +msgstr "插入一個連結" #: .\templates\wagtailadmin\chooser\external_link.html:2 msgid "Add an external link" -msgstr "添加一个外部链接" +msgstr "增加一個外部連結" #: .\templates\wagtailadmin\edit_handlers\chooser_panel.html:20 msgid "Clear choice" -msgstr "清除选择" +msgstr "清除選擇" #: .\templates\wagtailadmin\edit_handlers\chooser_panel.html:22 msgid "Choose another item" -msgstr "选择其他选项" +msgstr "選擇其他選項" #: .\templates\wagtailadmin\edit_handlers\chooser_panel.html:27 msgid "Choose an item" -msgstr "选择一个选项" +msgstr "選擇一個選項" #: .\templates\wagtailadmin\edit_handlers\inline_panel_child.html:5 msgid "Move up" -msgstr "向上移动" +msgstr "往上移動" #: .\templates\wagtailadmin\edit_handlers\inline_panel_child.html:6 msgid "Move down" -msgstr "向下移动" +msgstr "往下移動" #: .\templates\wagtailadmin\edit_handlers\inline_panel_child.html:8 #: .\templates\wagtailadmin\pages\confirm_delete.html:7 @@ -258,53 +259,53 @@ msgstr "向下移动" #: .\templates\wagtailadmin\pages\list.html:68 #: .\templates\wagtailadmin\pages\list.html:188 msgid "Delete" -msgstr "删除" +msgstr "刪除" #: .\templates\wagtailadmin\edit_handlers\page_chooser_panel.html:12 msgid "Choose another page" -msgstr "选择另外一个页面" +msgstr "選擇另外一個頁面" #: .\templates\wagtailadmin\home\pages_for_moderation.html:5 msgid "Pages awaiting moderation" -msgstr "这些页面在等待审核" +msgstr "這些頁面正等待審核" #: .\templates\wagtailadmin\home\pages_for_moderation.html:13 #: .\templates\wagtailadmin\home\recent_edits.html:12 #: .\templates\wagtailadmin\pages\list.html:101 msgid "Title" -msgstr "标题" +msgstr "標題" #: .\templates\wagtailadmin\home\pages_for_moderation.html:14 #: .\templates\wagtailadmin\pages\list.html:22 msgid "Parent" -msgstr "上一级" +msgstr "上一層" #: .\templates\wagtailadmin\home\pages_for_moderation.html:15 #: .\templates\wagtailadmin\pages\list.html:24 #: .\templates\wagtailadmin\pages\list.html:116 msgid "Type" -msgstr "类型" +msgstr "類型" #: .\templates\wagtailadmin\home\pages_for_moderation.html:16 msgid "Edited" -msgstr "" +msgstr "編輯" #: .\templates\wagtailadmin\home\pages_for_moderation.html:23 #: .\templates\wagtailadmin\home\recent_edits.html:21 #: .\templates\wagtailadmin\pages\list.html:167 #: .\templates\wagtailadmin\pages\list.html:176 msgid "Edit this page" -msgstr "编辑这个页面" +msgstr "編輯這個頁面" #: .\templates\wagtailadmin\home\pages_for_moderation.html:28 #: .\templates\wagtailadmin\pages\_moderator_userbar.html:12 msgid "Approve" -msgstr "通过" +msgstr "通過" #: .\templates\wagtailadmin\home\pages_for_moderation.html:34 #: .\templates\wagtailadmin\pages\_moderator_userbar.html:17 msgid "Reject" -msgstr "拒绝" +msgstr "拒絕" #: .\templates\wagtailadmin\home\pages_for_moderation.html:37 #: .\templates\wagtailadmin\home\recent_edits.html:23 @@ -312,17 +313,17 @@ msgstr "拒绝" #: .\templates\wagtailadmin\pages\list.html:56 #: .\templates\wagtailadmin\pages\list.html:176 msgid "Edit" -msgstr "编辑" +msgstr "編輯" #: .\templates\wagtailadmin\home\pages_for_moderation.html:38 #: .\templates\wagtailadmin\pages\create.html:24 #: .\templates\wagtailadmin\pages\edit.html:42 msgid "Preview" -msgstr "预览" +msgstr "預覽" #: .\templates\wagtailadmin\home\recent_edits.html:5 msgid "Your most recent edits" -msgstr "你最近的编辑" +msgstr "你最近的編輯" #: .\templates\wagtailadmin\home\recent_edits.html:13 msgid "Date" @@ -332,23 +333,23 @@ msgstr "日期" #: .\templates\wagtailadmin\pages\list.html:25 #: .\templates\wagtailadmin\pages\list.html:128 msgid "Status" -msgstr "状态" +msgstr "狀態" #: .\templates\wagtailadmin\home\recent_edits.html:25 #: .\templates\wagtailadmin\pages\list.html:59 #: .\templates\wagtailadmin\pages\list.html:179 msgid "View draft" -msgstr "查看草稿" +msgstr "觀看草稿" #: .\templates\wagtailadmin\home\recent_edits.html:28 #: .\templates\wagtailadmin\pages\list.html:62 #: .\templates\wagtailadmin\pages\list.html:182 msgid "View live" -msgstr "查看在线版" +msgstr "觀看線上版" #: .\templates\wagtailadmin\home\site_summary.html:3 msgid "Site summary" -msgstr "网站摘要" +msgstr "網站摘要" #: .\templates\wagtailadmin\home\site_summary.html:6 #, python-format @@ -360,7 +361,8 @@ msgid_plural "" "\n" " %(total_pages)s Pages\n" " " -msgstr[0] "" +msgstr[0] "\n %(total_pages)s 頁面\n " +msgstr[1] "\n %(total_pages)s 頁面\n " #: .\templates\wagtailadmin\home\site_summary.html:13 #, python-format @@ -372,7 +374,8 @@ msgid_plural "" "\n" " %(total_images)s Images\n" " " -msgstr[0] "" +msgstr[0] "\n %(total_images)s 圖片\n " +msgstr[1] "\n %(total_images)s 圖片\n " #: .\templates\wagtailadmin\home\site_summary.html:20 #, python-format @@ -384,50 +387,51 @@ msgid_plural "" "\n" " %(total_docs)s Documents\n" " " -msgstr[0] "" +msgstr[0] "\n %(total_docs)s 文件\n " +msgstr[1] "\n %(total_docs)s 文件\n " #: .\templates\wagtailadmin\notifications\approved.html:1 #, python-format msgid "The page \"%(title)s\" has been approved" -msgstr "这个页面 \"%(title)s\" 已经被通过" +msgstr "這個頁面 \"%(title)s\" 已經通過" #: .\templates\wagtailadmin\notifications\approved.html:2 #, python-format msgid "The page \"%(title)s\" has been approved." -msgstr "这个页面 \"%(title)s\" 已经被通过" +msgstr "這個頁面 \"%(title)s\" 已經通過" #: .\templates\wagtailadmin\notifications\approved.html:4 msgid "You can view the page here:" -msgstr "你可以在此查看这个页面" +msgstr "你可以在此觀看這個頁面" #: .\templates\wagtailadmin\notifications\rejected.html:1 #, python-format msgid "The page \"%(title)s\" has been rejected" -msgstr "这个页面 \"%(title)s\" 已经被拒绝" +msgstr "這個頁面 \"%(title)s\" 已經被拒絕" #: .\templates\wagtailadmin\notifications\rejected.html:2 #, python-format msgid "The page \"%(title)s\" has been rejected." -msgstr "这个页面 \"%(title)s\" 已经被拒绝" +msgstr "這個頁面 \"%(title)s\" 已經被拒絕" #: .\templates\wagtailadmin\notifications\rejected.html:4 #: .\templates\wagtailadmin\notifications\submitted.html:5 msgid "You can edit the page here:" -msgstr "你可以在此编辑这个页面:" +msgstr "你可以在此編輯這個頁面:" #: .\templates\wagtailadmin\notifications\submitted.html:1 #, python-format msgid "The page \"%(page)s\" has been submitted for moderation" -msgstr "这个页面 \"%(page)s\" 已经提交审核" +msgstr "這個頁面 \"%(page)s\" 已經送審" #: .\templates\wagtailadmin\notifications\submitted.html:2 #, python-format msgid "The page \"%(page)s\" has been submitted for moderation." -msgstr "这个页面 \"%(page)s\" 已经提交审核。" +msgstr "這個頁面 \"%(page)s\" 已經送審。" #: .\templates\wagtailadmin\notifications\submitted.html:4 msgid "You can preview the page here:" -msgstr "你可以在此预览这页:" +msgstr "你可以在此預覽這個頁面:" #: .\templates\wagtailadmin\pages\_moderator_userbar.html:4 #, python-format @@ -435,34 +439,34 @@ msgid "" "\n" " Previewing '%(title)s', submitted by %(submitted_by)s on %(submitted_on)s.\n" " " -msgstr "\n 预览 '%(title)s', %(submitted_by)s 在 %(submitted_on)s 提交.\n " +msgstr "\n 預覽 '%(title)s', %(submitted_by)s 在 %(submitted_on)s 送審。\n " #: .\templates\wagtailadmin\pages\add_subpage.html:6 #, python-format msgid "Create a page in %(title)s" -msgstr "以 %(title)s 为题创建一个页面" +msgstr "以 %(title)s 為題建立一個頁面" #: .\templates\wagtailadmin\pages\add_subpage.html:9 msgid "Create a page in" -msgstr "在这创建一个页面" +msgstr "在這建立一個頁面" #: .\templates\wagtailadmin\pages\add_subpage.html:13 msgid "Choose which type of page you'd like to create." -msgstr "选择你希望创建哪个类型的页面。" +msgstr "選擇希望建立的頁面類型。" #: .\templates\wagtailadmin\pages\add_subpage.html:26 #, python-format msgid "Pages using %(page_type)s" -msgstr "%(page_type)s 类的页面" +msgstr "%(page_type)s 類的頁面" #: .\templates\wagtailadmin\pages\confirm_delete.html:3 #, python-format msgid "Delete %(title)s" -msgstr "删除%(title)s" +msgstr "刪除 %(title)s" #: .\templates\wagtailadmin\pages\confirm_delete.html:12 msgid "Are you sure you want to delete this page?" -msgstr "你确定你要删除此页吗?" +msgstr "你確定要刪除這頁嗎?" #: .\templates\wagtailadmin\pages\confirm_delete.html:14 #, python-format @@ -474,77 +478,78 @@ msgid_plural "" "\n" " This will also delete %(descendant_count)s more subpages.\n" " " -msgstr[0] "" +msgstr[0] "\n 這也會刪除一個子頁面。 " +msgstr[1] "\n 這也會刪除 %(descendant_count)s 個子頁面。 " #: .\templates\wagtailadmin\pages\confirm_delete.html:22 msgid "" "Alternatively you can unpublish the page. This removes the page from public " "view and you can edit or publish it again later." -msgstr "你页可以取消发布此页。此页将不能从外部访问,你可以编辑后再次发布。" +msgstr "你可以選擇取消發佈此頁面。此頁面將將無法從外部觀看,你可以編輯後再次發。" #: .\templates\wagtailadmin\pages\confirm_delete.html:26 msgid "Delete it" -msgstr "删除" +msgstr "刪除" #: .\templates\wagtailadmin\pages\confirm_delete.html:26 msgid "Unpublish it" -msgstr "取消发布" +msgstr "取消發佈" #: .\templates\wagtailadmin\pages\confirm_move.html:3 #, python-format msgid "Move %(title)s" -msgstr "移动 %(title)s" +msgstr "移動 %(title)s" #: .\templates\wagtailadmin\pages\confirm_move.html:6 #: .\templates\wagtailadmin\pages\list.html:65 #: .\templates\wagtailadmin\pages\list.html:185 msgid "Move" -msgstr "移动" +msgstr "移動" #: .\templates\wagtailadmin\pages\confirm_move.html:11 #, python-format msgid "Are you sure you want to move this page into '%(title)s'?" -msgstr "你确定你想要移动这个页面至'%(title)s'吗?" +msgstr "你確定想要移動此頁面至 '%(title)s' 嗎?" #: .\templates\wagtailadmin\pages\confirm_move.html:13 #, python-format msgid "" "Are you sure you want to move this page and all of its children into " "'%(title)s'?" -msgstr "你确定你要移动这页和其所有子页面至'%(title)s'吗?" +msgstr "你確定要移動此頁面和其所有子頁面至 '%(title)s' 嗎?" #: .\templates\wagtailadmin\pages\confirm_move.html:18 msgid "Yes, move this page" -msgstr "是的,移动这页" +msgstr "是的,移動此頁面" #: .\templates\wagtailadmin\pages\confirm_unpublish.html:3 #, python-format msgid "Unpublish %(title)s" -msgstr "停止发布%(title)s" +msgstr "取消發佈 %(title)s" #: .\templates\wagtailadmin\pages\confirm_unpublish.html:6 #: .\templates\wagtailadmin\pages\edit.html:33 #: .\templates\wagtailadmin\pages\list.html:71 #: .\templates\wagtailadmin\pages\list.html:191 msgid "Unpublish" -msgstr "停止发布" +msgstr "取消發佈" #: .\templates\wagtailadmin\pages\confirm_unpublish.html:10 msgid "Are you sure you want to unpublish this page?" -msgstr "你确定你想停止发布这页吗?" +msgstr "你確定想取消發佈此頁面嗎?" #: .\templates\wagtailadmin\pages\confirm_unpublish.html:13 msgid "Yes, unpublish it" -msgstr "是的,停止发布" +msgstr "是的,取消發佈" #: .\templates\wagtailadmin\pages\content_type_use.html:7 msgid "Pages using" -msgstr "页面在用" +msgstr "頁面正在使用" #: .\templates\wagtailadmin\pages\create.html:5 #, python-format msgid "New %(page_type)s" -msgstr "新%(page_type)s类" +msgstr "新 %(page_type)s 分類" #: .\templates\wagtailadmin\pages\create.html:9 msgid "New" @@ -552,117 +557,117 @@ msgstr "新" #: .\templates\wagtailadmin\pages\create.html:21 msgid "Save as draft" -msgstr "保存为草稿" +msgstr "儲存為草稿" #: .\templates\wagtailadmin\pages\create.html:26 #: .\templates\wagtailadmin\pages\edit.html:39 msgid "Publish" -msgstr "发布" +msgstr "發佈" #: .\templates\wagtailadmin\pages\create.html:28 #: .\templates\wagtailadmin\pages\edit.html:41 msgid "Submit for moderation" -msgstr "提交审核" +msgstr "送審" #: .\templates\wagtailadmin\pages\edit.html:5 #, python-format msgid "Editing %(title)s" -msgstr "编辑%(title)s" +msgstr "編輯 %(title)s" #: .\templates\wagtailadmin\pages\edit.html:12 #, python-format msgid "Editing %(title)s" -msgstr "编辑%(title)s" +msgstr "編輯 %(title)s" #: .\templates\wagtailadmin\pages\edit.html:15 msgid "Status:" -msgstr "状态:" +msgstr "狀態:" #: .\templates\wagtailadmin\pages\edit.html:29 msgid "Save draft" -msgstr "保存草稿" +msgstr "儲存草稿" #: .\templates\wagtailadmin\pages\edit.html:52 #, python-format msgid "Last modified: %(last_mod)s" -msgstr "上一次编辑:%(last_mod)s" +msgstr "上一次編輯:%(last_mod)s" #: .\templates\wagtailadmin\pages\edit.html:54 #, python-format msgid "by %(modified_by)s" -msgstr "作者%(modified_by)s" +msgstr "作者 %(modified_by)s" #: .\templates\wagtailadmin\pages\index.html:4 #, python-format msgid "Exploring %(title)s" -msgstr "浏览%(title)s" +msgstr "瀏覽%(title)s" #: .\templates\wagtailadmin\pages\list.html:53 #: .\templates\wagtailadmin\pages\list.html:194 msgid "Add child page" -msgstr "添加子页面" +msgstr "增加子頁面" #: .\templates\wagtailadmin\pages\list.html:94 msgid "Disable ordering of child pages" -msgstr "禁止自页面的顺序" +msgstr "禁止子頁面的排序" #: .\templates\wagtailadmin\pages\list.html:94 #: .\templates\wagtailadmin\pages\list.html:96 msgid "Order" -msgstr "顺序" +msgstr "排序" #: .\templates\wagtailadmin\pages\list.html:96 msgid "Enable ordering of child pages" -msgstr "开启子页面顺序" +msgstr "開啟子頁面排序" #: .\templates\wagtailadmin\pages\list.html:149 msgid "Drag" -msgstr "拖动" +msgstr "拖曳" #: .\templates\wagtailadmin\pages\list.html:220 #: .\templates\wagtailadmin\pages\list.html:224 #, python-format msgid "Explorer subpages of '%(title)s'" -msgstr "浏览 '%(title)s' 的子页面" +msgstr "瀏覽 '%(title)s' 的子頁面" #: .\templates\wagtailadmin\pages\list.html:220 #: .\templates\wagtailadmin\pages\list.html:224 #: .\templates\wagtailadmin\pages\list.html:228 msgid "Explore" -msgstr "浏览" +msgstr "瀏覽" #: .\templates\wagtailadmin\pages\list.html:228 #, python-format msgid "Explorer child pages of '%(title)s'" -msgstr "浏览 '%(title)s' 的子页面" +msgstr "瀏覽 '%(title)s' 的子頁面" #: .\templates\wagtailadmin\pages\list.html:230 #, python-format msgid "Add a child page to '%(title)s'" -msgstr "添加子页面至'%(title)s'" +msgstr "增加子頁面至 '%(title)s'" #: .\templates\wagtailadmin\pages\list.html:230 msgid "Add subpage" -msgstr "添加子页面" +msgstr "增加子頁面" #: .\templates\wagtailadmin\pages\list.html:239 msgid "No pages have been created." -msgstr "没有已保存的页面" +msgstr "沒有已儲存的頁面" #: .\templates\wagtailadmin\pages\list.html:239 #, python-format msgid "Why not add one?" -msgstr "为什么不添加一页?" +msgstr "為什麼不 增加一個頁面呢?" #: .\templates\wagtailadmin\pages\move_choose_destination.html:3 #, python-format msgid "Select a new parent page for %(title)s" -msgstr "为%(title)s选择一个新的根页面" +msgstr "為 %(title)s 選擇一個新的母頁面" #: .\templates\wagtailadmin\pages\move_choose_destination.html:7 #, python-format msgid "Select a new parent page for %(title)s" -msgstr "为%(title)s选择一个新的根页面" +msgstr "為 %(title)s 選擇一個新的母頁面" #: .\templates\wagtailadmin\pages\search_results.html:6 #, python-format @@ -674,7 +679,8 @@ msgid_plural "" "\n" " There are %(counter)s matches\n" " " -msgstr[0] "" +msgstr[0] "\n 有一個符合" +msgstr[1] "\n 有 $(counter)s 個符合" #: .\templates\wagtailadmin\pages\search_results.html:17 #, python-format @@ -682,7 +688,7 @@ msgid "" "\n" " Page %(page_number)s of %(num_pages)s.\n" " " -msgstr "\n 第 %(page_number)s / %(num_pages)s页.\n " +msgstr "\n 第 %(page_number)s / %(num_pages)s頁。\n " #: .\templates\wagtailadmin\pages\search_results.html:24 #: .\templates\wagtailadmin\pages\search_results.html:26 @@ -690,7 +696,7 @@ msgstr "\n 第 %(page_number)s / %(num_pages)s页.\n " #: .\templates\wagtailadmin\shared\pagination_nav.html:10 #: .\templates\wagtailadmin\shared\pagination_nav.html:14 msgid "Previous" -msgstr "向前" +msgstr "往前" #: .\templates\wagtailadmin\pages\search_results.html:33 #: .\templates\wagtailadmin\pages\search_results.html:35 @@ -698,40 +704,40 @@ msgstr "向前" #: .\templates\wagtailadmin\shared\pagination_nav.html:23 #: .\templates\wagtailadmin\shared\pagination_nav.html:25 msgid "Next" -msgstr "往后" +msgstr "往後" #: .\templates\wagtailadmin\pages\search_results.html:43 #, python-format msgid "Sorry, no pages match \"%(query_string)s\"" -msgstr "" +msgstr "對不起,沒有任何頁面符合 \"%(query_string)s\"" #: .\templates\wagtailadmin\pages\search_results.html:45 msgid "Enter a search term above" -msgstr "请在上面输入搜索词" +msgstr "請輸入關鍵字" #: .\templates\wagtailadmin\pages\select_location.html:3 #, python-format msgid "Where do you want to create a %(page_type)s" -msgstr "你想在哪创建 %(page_type)s" +msgstr "你想在哪建立 %(page_type)s" #: .\templates\wagtailadmin\pages\select_location.html:5 msgid "Where do you want to create this" -msgstr "你想在哪创建这个" +msgstr "你想在哪建立這個" #: .\templates\wagtailadmin\pages\select_type.html:3 #: .\templates\wagtailadmin\pages\select_type.html:6 msgid "Create a new page" -msgstr "创建一个新页面" +msgstr "建立一個新頁面" #: .\templates\wagtailadmin\pages\select_type.html:10 msgid "" "Your new page will be saved in the top level of your website. You " "can move it after saving." -msgstr "你的新页面将会保存到网站的顶级 你 在保存后可以移动." +msgstr "你的新頁面將會儲存到網站的 最上層 你可以在儲存後移動它。" #: .\templates\wagtailadmin\shared\main_nav.html:15 msgid "Account settings" -msgstr "账号设置" +msgstr "帳號設定" #: .\templates\wagtailadmin\shared\main_nav.html:16 msgid "Log out" @@ -743,20 +749,20 @@ msgstr "更多" #: .\templates\wagtailadmin\shared\main_nav.html:22 msgid "Redirects" -msgstr "转向" +msgstr "重導向" #: .\templates\wagtailadmin\shared\main_nav.html:23 msgid "Editors Picks" -msgstr "编辑手摘" +msgstr "編者精選" #: .\templates\wagtailadmin\shared\pagination_nav.html:3 #, python-format msgid "Page %(page_num)s of %(total_pages)s." -msgstr "第%(page_num)s页 共%(total_pages)s页" +msgstr "第 %(page_num)s 頁 共 %(total_pages)s 頁" #: .\templatetags\wagtailadmin_nav.py:52 msgid "Images" -msgstr "图像" +msgstr "圖片" #: .\templatetags\wagtailadmin_nav.py:56 msgid "Documents" @@ -772,66 +778,66 @@ msgstr "使用者" #: .\views\account.py:26 msgid "Your password has been changed successfully!" -msgstr "您的密码已经更改成功。" +msgstr "您的密碼已經更改成功。" #: .\views\pages.py:99 msgid "Sorry, you do not have access to create a page of type '{0}'." -msgstr "对不起,你没有创建'{0}'类型页面的权限。" +msgstr "對不起,你沒有建立 '{0}' 類型頁面的權限。" #: .\views\pages.py:103 msgid "" "Pages of this type can only be created as children of '{0}'. This " "new page will be saved there." -msgstr "这一类的页面只能创建为'{0}'的子页面。这一页将会保存在那。" +msgstr "這一類的頁面只能建立為 '{0}' 的子頁面。此頁面將會儲存在那邊。" #: .\views\pages.py:166 msgid "This slug is already in use" -msgstr "这个唯一的地址已被占用" +msgstr "這個地址已被使用" #: .\views\pages.py:187 .\views\pages.py:254 .\views\pages.py:589 msgid "Page '{0}' published." -msgstr "第 '{0}' 页已发布。" +msgstr "第 '{0}' 頁已發佈。" #: .\views\pages.py:189 .\views\pages.py:256 msgid "Page '{0}' submitted for moderation." -msgstr "第 '{0}' 页已提交审核。" +msgstr "第 '{0}' 頁已送審。" #: .\views\pages.py:192 msgid "Page '{0}' created." -msgstr "第 '{0}' 页已创建。" +msgstr "第 '{0}' 頁已建立。" #: .\views\pages.py:201 msgid "The page could not be created due to errors." -msgstr "这一页因有错误发生而无法创建。" +msgstr "這頁面因有錯誤而無法建立。" #: .\views\pages.py:259 msgid "Page '{0}' updated." -msgstr "第 '{0}' 页已更新" +msgstr "第 '{0}' 頁已更新" #: .\views\pages.py:268 msgid "The page could not be saved due to validation errors" -msgstr "这页无法保存,因为页面发生验证错误" +msgstr "這頁面因有驗證錯誤而無法儲存。" #: .\views\pages.py:280 msgid "This page is currently awaiting moderation" -msgstr "这页正在等待审核" +msgstr "這頁正等待審核" #: .\views\pages.py:298 msgid "Page '{0}' deleted." -msgstr "第 '{0}' 页已删除" +msgstr "第 '{0}' 頁已刪除" #: .\views\pages.py:428 msgid "Page '{0}' unpublished." -msgstr "第 '{0}' 页已停止发布" +msgstr "第 '{0}' 頁已取消發佈" #: .\views\pages.py:479 msgid "Page '{0}' moved." -msgstr "第 '{0}' 页已移动。" +msgstr "第 '{0}' 頁已移動。" #: .\views\pages.py:584 .\views\pages.py:602 .\views\pages.py:621 msgid "The page '{0}' is not currently awaiting moderation." -msgstr "第 '{0}' 页当前不需要等待审核。" +msgstr "第 '{0}' 頁目前不需要等待審核。" #: .\views\pages.py:608 msgid "Page '{0}' rejected for publication." -msgstr "第 '{0}' 页已被拒绝发布。" +msgstr "第 '{0}' 頁已被拒絕發佈。" From efed0adb10f73f403d05deaa6441f3ad881fc266 Mon Sep 17 00:00:00 2001 From: dv Date: Sat, 3 May 2014 23:17:05 +0800 Subject: [PATCH 05/57] add zh_TW translation for wagtaildocs --- .../locale/zh_TW/LC_MESSAGES/django.mo | Bin 0 -> 2328 bytes .../locale/zh_TW/LC_MESSAGES/django.po | 157 ++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 wagtail/wagtaildocs/locale/zh_TW/LC_MESSAGES/django.mo create mode 100644 wagtail/wagtaildocs/locale/zh_TW/LC_MESSAGES/django.po diff --git a/wagtail/wagtaildocs/locale/zh_TW/LC_MESSAGES/django.mo b/wagtail/wagtaildocs/locale/zh_TW/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..195d80cc4fff29c4d1322e3a15dd2f6272c71709 GIT binary patch literal 2328 zcmb7@U2IfE6vqd|4^~jbZxA!7Hf;m9>=sa5+M<>=Apu2LM2yL1*gNblxqENDGfS<8 zWFaMmwjh2KC=h9zN(d^&qO$fwpGh# z3955Efh5)X8t@UY4ODhfP~~Z9`2eWS*P}V4nFZmBe6RTfsP_G=IDX^{;?6kfU1e);tcXy7q%A@AF^+90gU2Ro_+LaQu=T%3m6)W@@Nds_!c> zReWqK^$jSUU)>osR1L~wnf_4q#dRTzG1b}B2w*;dscM3wkw-DhL){CNPS`grRU8!DqWKYivj292Ha2VsYluSi(uh zIN9WTudbCzY4JKyR+J-=O*&gz^H%Uc4P~au&H8_9{T%1&)9ogc+^m=j(rPAU(vFvj zdX)pWB`r?2z+A{mu7d1f`#ITxgkuSf*^7?rcCMl}ilnpDMW*RuNB{#`Ed8 zFd|Nv2DZHzFElgjBW>_XvC z!^$8=U<(t{h`7ua7L$$}rXA+~wNI~GpP-H9uV>>aoUA_Pq?%!F$I~p%jRn_^9`{%pn5v;!q#SWqZ6sR|!t9zw)O?3un3z-Y*qFtNcX# k_1wfnZmQpp05`O7XgoKODUMGfZTdeRwf0uJD*luH2cp;LivR!s literal 0 HcmV?d00001 diff --git a/wagtail/wagtaildocs/locale/zh_TW/LC_MESSAGES/django.po b/wagtail/wagtaildocs/locale/zh_TW/LC_MESSAGES/django.po new file mode 100644 index 000000000..b2d46ac09 --- /dev/null +++ b/wagtail/wagtaildocs/locale/zh_TW/LC_MESSAGES/django.po @@ -0,0 +1,157 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: Wagtail\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-03-14 23:09+0200\n" +"PO-Revision-Date: 2014-03-14 21:12+0000\n" +"Last-Translator: wdv4758h \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: .\models.py:16 .\templates\wagtaildocs\documents\list.html:9 +msgid "Title" +msgstr "標題" + +#: .\models.py:17 .\templates\wagtaildocs\documents\list.html:18 +msgid "File" +msgstr "文件" + +#: .\models.py:21 +msgid "Tags" +msgstr "標籤" + +#: .\templates\wagtaildocs\chooser\chooser.html:2 +#: .\templates\wagtaildocs\edit_handlers\document_chooser_panel.html:11 +msgid "Choose a document" +msgstr "選擇一個文件" + +#: .\templates\wagtaildocs\chooser\chooser.html:7 +#: .\templates\wagtaildocs\chooser\chooser.html:19 +msgid "Search" +msgstr "搜尋" + +#: .\templates\wagtaildocs\chooser\chooser.html:8 +msgid "Upload" +msgstr "上傳" + +#: .\templates\wagtaildocs\chooser\chooser.html:34 +#: .\templates\wagtaildocs\documents\add.html:25 +#: .\templates\wagtaildocs\documents\edit.html:29 +msgid "Save" +msgstr "儲存" + +#: .\templates\wagtaildocs\chooser\results.html:5 +#: .\templates\wagtaildocs\documents\results.html:5 +#, python-format +msgid "" +"\n" +" There is one match\n" +" " +msgid_plural "" +"\n" +" There are %(counter)s matches\n" +" " +msgstr[0] "\n 有一個符合" +msgstr[1] "\n 有 $(counter)s 個符合" + +#: .\templates\wagtaildocs\chooser\results.html:12 +msgid "Latest documents" +msgstr "最新文件" + +#: .\templates\wagtaildocs\chooser\results.html:19 +#: .\templates\wagtaildocs\documents\results.html:18 +#, python-format +msgid "Sorry, no documents match \"%(query_string)s\"" +msgstr "對不起,沒有文件符合 \"%(query_string)s\"" + +#: .\templates\wagtaildocs\documents\_file_field.html:5 +msgid "Change document:" +msgstr "修改文件:" + +#: .\templates\wagtaildocs\documents\add.html:4 +#: .\templates\wagtaildocs\documents\index.html:17 +msgid "Add a document" +msgstr "增加一份文件" + +#: .\templates\wagtaildocs\documents\add.html:15 +msgid "Add document" +msgstr "增加文件" + +#: .\templates\wagtaildocs\documents\confirm_delete.html:3 +#, python-format +msgid "Delete %(title)s" +msgstr "刪除 %(title)s" + +#: .\templates\wagtaildocs\documents\confirm_delete.html:6 +#: .\templates\wagtaildocs\documents\edit.html:29 +msgid "Delete document" +msgstr "刪除文件" + +#: .\templates\wagtaildocs\documents\confirm_delete.html:10 +msgid "Are you sure you want to delete this document?" +msgstr "你確定你要刪除這份文件嗎?" + +#: .\templates\wagtaildocs\documents\confirm_delete.html:13 +msgid "Yes, delete" +msgstr "是的,刪除" + +#: .\templates\wagtaildocs\documents\edit.html:4 +#, python-format +msgid "Editing %(title)s" +msgstr "編輯 %(title)s" + +#: .\templates\wagtaildocs\documents\edit.html:15 +msgid "Editing" +msgstr "編輯" + +#: .\templates\wagtaildocs\documents\index.html:16 +msgid "Documents" +msgstr "文件" + +#: .\templates\wagtaildocs\documents\list.html:20 +msgid "Uploaded" +msgstr "已上傳" + +#: .\templates\wagtaildocs\documents\results.html:21 +#, python-format +msgid "" +"You haven't uploaded any documents. Why not upload one now?" +msgstr "你沒有上傳任何文件。 為什麼不 上傳一份?" + +#: .\templates\wagtaildocs\edit_handlers\document_chooser_panel.html:9 +msgid "Clear choice" +msgstr "清除選擇" + +#: .\templates\wagtaildocs\edit_handlers\document_chooser_panel.html:10 +msgid "Choose another document" +msgstr "選擇另外一份文件" + +#: .\views\documents.py:34 .\views\documents.py:43 +msgid "Search documents" +msgstr "搜尋文件" + +#: .\views\documents.py:83 +msgid "Document '{0}' added." +msgstr "文件 '{0}' 已加入" + +#: .\views\documents.py:86 .\views\documents.py:115 +msgid "The document could not be saved due to errors." +msgstr "這文件因有錯誤而無法建立。" + +#: .\views\documents.py:112 +msgid "Document '{0}' updated" +msgstr "文件 '{0}' 已更新" + +#: .\views\documents.py:134 +msgid "Document '{0}' deleted." +msgstr "文件 '{0}' 已刪除" From 616ba10b9f534d8fb5d4d003d73f2e2d2f58f7e2 Mon Sep 17 00:00:00 2001 From: dv Date: Sat, 3 May 2014 23:21:35 +0800 Subject: [PATCH 06/57] add zh_TW translation for wagtailembeds --- .../locale/zh_TW/LC_MESSAGES/django.mo | Bin 0 -> 1011 bytes .../locale/zh_TW/LC_MESSAGES/django.po | 54 ++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 wagtail/wagtailembeds/locale/zh_TW/LC_MESSAGES/django.mo create mode 100644 wagtail/wagtailembeds/locale/zh_TW/LC_MESSAGES/django.po diff --git a/wagtail/wagtailembeds/locale/zh_TW/LC_MESSAGES/django.mo b/wagtail/wagtailembeds/locale/zh_TW/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..7a51d6e230bef21b9d705cd90f5f082f297d1242 GIT binary patch literal 1011 zcmZuvO=}ZT6dkpG5M8+t1s7M{SjxmCrnXLvsI`?sgCV5Wg-~9S*U8w)OnCFsHm*Xc z($ds|kVQ*DDpadd6-1~ITr0Tn7r3!AO+o0wKj4`pwIW_}a%S$_d+vEN_xtg-s)9HI zoCfXzM}cL)kI%qa;0tgF_z4^XegP)|WuKxXL8rhYU=w@*{1to`_y(NAeLIqVe;n-h zr@$w`3>*Ycf^UIefbmmy@Q2n$w6)mJ?*|S82La!+ui1!RW?8nRQNzj-vxw)@JWHdt zAel298cGfZl>y7)Lbj+`p(ISs98TPlTo9viW*S+)T1n-&;N)W-SSH3}qdr_^4-nMARA6H*#QLgAFlGylCbHwvuFmcpUD>_5rsv@(n6dL$QEur)rgJsLSss4k z1M$8+^Wk79&}-xKSkNpLU{3N$d7)t9;60SdF@YBx8%p)7-FtQZ>`^Y%J}YBq@fJ1e zP8;&iB#j>AMpDCpgjp2KRQqj_cQmpJjaw%c>7nLj?7T&1Via!g2`KLJ+ID%-EzkMe zL7N-vThlAv`>Hql$(?!ES|)GdiTiL>X;Ld!e?3>PZ6NI}&wACFt)=P4dNsc3-r^9R zy48j4mCBFu6k5Dj&%CFr^|f{P%@Q*HboWCADt~!^l(#tLmKS$wmEG0ZtkpI@K8DzK VTNkRYs literal 0 HcmV?d00001 diff --git a/wagtail/wagtailembeds/locale/zh_TW/LC_MESSAGES/django.po b/wagtail/wagtailembeds/locale/zh_TW/LC_MESSAGES/django.po new file mode 100644 index 000000000..43227b1dc --- /dev/null +++ b/wagtail/wagtailembeds/locale/zh_TW/LC_MESSAGES/django.po @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- + +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: Lihan Li , 2014 +msgid "" +msgstr "" +"Project-Id-Version: Wagtail\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-02-22 19:56+0200\n" +"PO-Revision-Date: 2014-02-24 17:34+0000\n" +"Last-Translator: wdv4758h \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: .\forms.py:11 +msgid "Please enter a valid URL" +msgstr "請輸入有效的 URL" + +#: .\forms.py:15 +msgid "URL" +msgstr "URL" + +#: .\templates\wagtailembeds\chooser\chooser.html:3 +msgid "Insert embed" +msgstr "插入 embed" + +#: .\templates\wagtailembeds\chooser\chooser.html:14 +msgid "Insert" +msgstr "插入" + +#: .\views\chooser.py:34 +msgid "" +"There seems to be a problem with your embedly API key. Please check your " +"settings." +msgstr "embedly API key 有問題。請檢查設定。" + +#: .\views\chooser.py:36 +msgid "Cannot find an embed for this URL." +msgstr "在這個 URL 中無法找到 embed" + +#: .\views\chooser.py:38 +msgid "" +"There seems to be an error with Embedly while trying to embed this URL. " +"Please try again later." +msgstr "" +"在嵌入這個 URL 的時候,Embedly 似乎有錯。" +"請稍候再試." From bf75ba89528acc6862504d53242f0cab22c91e88 Mon Sep 17 00:00:00 2001 From: dv Date: Sat, 3 May 2014 23:34:41 +0800 Subject: [PATCH 07/57] add zh_TW translation for wagtailimages --- .../locale/zh_TW/LC_MESSAGES/django.mo | Bin 0 -> 2629 bytes .../locale/zh_TW/LC_MESSAGES/django.po | 170 ++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 wagtail/wagtailimages/locale/zh_TW/LC_MESSAGES/django.mo create mode 100644 wagtail/wagtailimages/locale/zh_TW/LC_MESSAGES/django.po diff --git a/wagtail/wagtailimages/locale/zh_TW/LC_MESSAGES/django.mo b/wagtail/wagtailimages/locale/zh_TW/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..203f1dd38efbc9a4c3d67359736b6bb2ea88142c GIT binary patch literal 2629 zcma)+Uu+ab9LGlml~WP%4=RE~1ECGw>$RYgqb+D@O%25ghlHqUmfPvwlI`xfe_D$n zxgtoRtsv3@rP0z3kAn|`X9Yh4 zAH#eMd;t6j78FzXQ464`2oO3y2?CvX~GFTnh5|D?$875+A-#2YI{>xF75QUqel@U=8NaBX}O? zL6FDO1Fi-8L7xA&V*O{qKfos;{|n^$OYaZ366F4h!6(2nF|Px8T^aL+}8gzapxJth5N5N;&d3y?-$IaVnbbbeLHT<*S_Y&^? z^8@^ba{BFQL5@ezd98WA(`^|BC=D(aozr4TW-_W;)X*7ik?nYLX8BHvGL+X9#|=lf znOR~5JD4@Q=S4-KvQE_&Il%~@h!OU+8xFM`F=&%@o7x6dn8s{I?Ic3*RkxCwq^u_p z6E_jX%rGoQW!h|*h;L>-?PGdfH*BOL+|_7Io*r)xJOpvnDypsO2_hJ%BO_b2HCAGg zI#pw&o_nV2-;EqvPh~}6N_d_q2>BmEC#A^tjHX5Eb&Hv{2xkYDEHSajPQykzt+J+y z>WI|Bv=Lz=SI5scp*EM&11XlEhDlR;f;J;Is_K@_WH@g$QjUfsZ8>3)-Eu16*FtfeMvQ5;a#HuWVu!zLCMcfNf92~Z$z<^En zGa5G;Pm?MR&di|9G!4@V|C_djuomj_Qj9@v%Z!2o*aJ_du6>{ z1Rkb)lkNUurA(71YpyCRA1v|?j4Qn4XY5s5%i+QnK`ZuAa%<-lMp-HEND2Yf>Hl zcUF|@DSv8Jm2aWJuqv`8H2;n8299UP({8#e_xUCFROf<4x^~XfF{|bdee9kX40gH$ zeYxYuNFWlE?9^axXu|!nKYyvi?Yvw#KU_$k$M#^^J^R7!%qPUV@RfJwn?Q6s(@zQ= zcl&F8oPymZy=2&G0Beic;`k@cdxfI*MB6C z2I<~PAI@Lt%AFaZcu8)hJN&1_>+H*?kNVF^pf$6J+Tol zh<9qhz1k%pyt-F=;5dJC>~^NxyMCG<`{ZPHsyA2;4*x%&m}wXOVY?RwVWH4HnooCg zv+qsihpxDj6S*s0$U)R#R_XFE^m0codN+E55V;Zz7A|&^?Dz@y@C|~JAP)o=92}V& gW1upVHa6!DPh=<4g^3KD)Bpdt%)7N84h0X)-zAq@y#N3J literal 0 HcmV?d00001 diff --git a/wagtail/wagtailimages/locale/zh_TW/LC_MESSAGES/django.po b/wagtail/wagtailimages/locale/zh_TW/LC_MESSAGES/django.po new file mode 100644 index 000000000..0fd9bc93c --- /dev/null +++ b/wagtail/wagtailimages/locale/zh_TW/LC_MESSAGES/django.po @@ -0,0 +1,170 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: Wagtail\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-03-14 23:02+0200\n" +"PO-Revision-Date: 2014-03-14 21:12+0000\n" +"Last-Translator: wdv4758h \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: .\models.py:22 +msgid "Title" +msgstr "標題" + +#: .\models.py:39 +msgid "Not a valid image format. Please use a gif, jpeg or png file instead." +msgstr "不是有效的圖片格式。請用 gif、jpeg 或者 png 格式的圖片" + +#: .\models.py:41 +msgid "File" +msgstr "文件" + +#: .\models.py:47 +msgid "Tags" +msgstr "標籤" + +#: .\templates\wagtailimages\chooser\chooser.html:3 +#: .\templates\wagtailimages\edit_handlers\image_chooser_panel.html:19 +msgid "Choose an image" +msgstr "選擇一個圖片" + +#: .\templates\wagtailimages\chooser\chooser.html:8 +#: .\templates\wagtailimages\chooser\chooser.html:20 +msgid "Search" +msgstr "搜尋" + +#: .\templates\wagtailimages\chooser\chooser.html:9 +#: .\templates\wagtailimages\chooser\chooser.html:43 +msgid "Upload" +msgstr "上傳" + +#: .\templates\wagtailimages\chooser\chooser.html:23 +msgid "Popular tags" +msgstr "熱門的標籤" + +#: .\templates\wagtailimages\chooser\results.html:6 +#: .\templates\wagtailimages\images\results.html:6 +#, python-format +msgid "" +"\n" +" There is one match\n" +" " +msgid_plural "" +"\n" +" There are %(counter)s matches\n" +" " +msgstr[0] "\n 有一個符合" +msgstr[1] "\n 有 $(counter)s 個符合" + +#: .\templates\wagtailimages\chooser\results.html:13 +#: .\templates\wagtailimages\images\results.html:13 +msgid "Latest images" +msgstr "最新圖片" + +#: .\templates\wagtailimages\chooser\select_format.html:3 +msgid "Choose a format" +msgstr "選擇一個格式" + +#: .\templates\wagtailimages\chooser\select_format.html:17 +msgid "Insert image" +msgstr "插入圖片" + +#: .\templates\wagtailimages\edit_handlers\image_chooser_panel.html:17 +msgid "Clear image" +msgstr "清除圖片" + +#: .\templates\wagtailimages\edit_handlers\image_chooser_panel.html:18 +msgid "Choose another image" +msgstr "選擇另外一個圖片" + +#: .\templates\wagtailimages\images\_file_field.html:6 +msgid "Change image:" +msgstr "更改圖片:" + +#: .\templates\wagtailimages\images\add.html:4 +#: .\templates\wagtailimages\images\index.html:19 +msgid "Add an image" +msgstr "增加一個圖片" + +#: .\templates\wagtailimages\images\add.html:15 +msgid "Add image" +msgstr "增加圖片" + +#: .\templates\wagtailimages\images\add.html:25 +#: .\templates\wagtailimages\images\edit.html:33 +msgid "Save" +msgstr "儲存" + +#: .\templates\wagtailimages\images\confirm_delete.html:4 +#: .\templates\wagtailimages\images\confirm_delete.html:8 +#: .\templates\wagtailimages\images\edit.html:33 +msgid "Delete image" +msgstr "刪除圖片" + +#: .\templates\wagtailimages\images\confirm_delete.html:16 +msgid "Are you sure you want to delete this image?" +msgstr "你確定要刪除這個圖片嗎?" + +#: .\templates\wagtailimages\images\confirm_delete.html:19 +msgid "Yes, delete" +msgstr "是的,刪除" + +#: .\templates\wagtailimages\images\edit.html:4 +#, python-format +msgid "Editing image %(title)s" +msgstr "編輯圖片 %(title)s" + +#: .\templates\wagtailimages\images\edit.html:15 +msgid "Editing" +msgstr "編輯" + +#: .\templates\wagtailimages\images\index.html:5 +#: .\templates\wagtailimages\images\index.html:18 +msgid "Images" +msgstr "圖片" + +#: .\templates\wagtailimages\images\results.html:31 +#, python-format +msgid "Sorry, no images match \"%(query_string)s\"" +msgstr "對不起,沒有任何圖片符合 \"%(query_string)s\"" + +#: .\templates\wagtailimages\images\results.html:34 +#, python-format +msgid "" +"You've not uploaded any images. Why not add one now?" +msgstr "沒有任何上傳的圖片。為什麼不 增加一個呢?" + +#: .\views\images.py:29 .\views\images.py:40 +msgid "Search images" +msgstr "搜尋圖片" + +#: .\views\images.py:92 +msgid "Image '{0}' updated." +msgstr "圖片 '{0}' 已更新" + +#: .\views\images.py:95 +msgid "The image could not be saved due to errors." +msgstr "圖片因有錯誤而無法儲存。" + +#: .\views\images.py:114 +msgid "Image '{0}' deleted." +msgstr "圖片 '{0}' 已刪除." + +#: .\views\images.py:132 +msgid "Image '{0}' added." +msgstr "圖片 '{0}' 已加入." + +#: .\views\images.py:135 +msgid "The image could not be created due to errors." +msgstr "圖片因有錯而不能被建立。" From 7a64b733c79a355308e42cc53538679e9b51ff57 Mon Sep 17 00:00:00 2001 From: dv Date: Sat, 3 May 2014 23:42:25 +0800 Subject: [PATCH 08/57] add zh_TW translation for wagtailredirects --- .../locale/zh_TW/LC_MESSAGES/django.mo | Bin 0 -> 2636 bytes .../locale/zh_TW/LC_MESSAGES/django.po | 151 ++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 wagtail/wagtailredirects/locale/zh_TW/LC_MESSAGES/django.mo create mode 100644 wagtail/wagtailredirects/locale/zh_TW/LC_MESSAGES/django.po diff --git a/wagtail/wagtailredirects/locale/zh_TW/LC_MESSAGES/django.mo b/wagtail/wagtailredirects/locale/zh_TW/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..03ae1357d3b47d082a6e62f81ed71572010985c6 GIT binary patch literal 2636 zcmb7^TWl0n7{?EaxAl&Q_vEC3w5!arTS_ELTdYtb31}^gjhCbuc20MP?9QxbW?NRH zSrB5S6pPZP+-hl{X+Z4;FqF0gAAIxO#0QCqJ9|kK5?@Tz2mfbgc6JL5i6@=?&H2uM z&iQUV*Ox6FCKxZ^c^=QwC4~6F-$5~k?jqzp@Cf)2cmoW8|A6;`FWybaqhJVp25bYD zf$xI%fg1QY*b6FPKllLn2bcx_0+)k(mJ;$5IOy^$_%P;IL9ySD;1l3=P<;O(ZguoV<_=mPOa zO#F!RKL&;F04V$%2J69}T`utvf>aVeDD)C2{AqIM?Vu>B(BRefy;5_Lf01J`gb!jo zhey-{Zjwjvh}?@hiWn;6*~$wjax3a3axL-;x9t1^wjY9G2;Y!uZ-|&gU#+NEe6(gn z;*2w@8dTR9P0D68?kyAVP3Rq=4DqUlsGinL#{Gu#1v5M)X;T!+nWAzQHAx%P89hyn zwENO0YbG^ys;~qz88zcLxT4-jHrrMgp8eK2&No#v!TbhkS5$0QyNPX5wOEBU;@5R= zOM}McUPgB@rqL*8vdNSH?TTlprkk``rg6@CTIyCc^vN+(RudHujc!>{x+}BpG*9@A zx>ndk@|xGkts6-P<4IX#nn^lYR8JzY}zbydUrX~r|%hRIP$ztOw~#yWxq^z;-Ri0p`R?P8S@QYDR+(kbIy=SJWT9~f{; zxlOKvX z&|&zt$%ZLKxU3lo+0=QM_9?whFRxo4r_GhOS7J%DYXFVc3b__bqkE(Xlaugg`_}F4 zRppl_3oe_{=LBI+y zU8?Dw6s8}v;wI#U0xA1N$oct_5leMw~#jhu= zq5j(z>B^cbrz*21#;k+m%0^cq_NgYwnHW<*CyA^esCP$LgX+UAXXth-Pjse|6Zpe8Jj(!TM&jcznNi(r?*) z#eK8+xomlMK0h<~zpoo7XeV9Hom0ro`*qz2#FA-myqb{@SU+ z&`B#dV9gH~zC3JQ8!b(ZmiiAm$_7tb`tEXhZp?pk{!o5qGCy;)aP&%{f5^%W7DjT8 z*4lf#cxeLLAQ<9(XJ0h+R78Dn+&XY}(G|Nai>(w+T*Cg<6~~L}-0IIcK|3xiT(Hya zEZaAb=M!-XK%Bs9%(+1%A7>!S+LCz+rxWjZA$eNs#5ihRJ~UlAcczp*RNQ~MaB&<(__}y04a=4qi5h7b=x&RGgq42Oa22BSdmx& literal 0 HcmV?d00001 diff --git a/wagtail/wagtailredirects/locale/zh_TW/LC_MESSAGES/django.po b/wagtail/wagtailredirects/locale/zh_TW/LC_MESSAGES/django.po new file mode 100644 index 000000000..fd0a433fe --- /dev/null +++ b/wagtail/wagtailredirects/locale/zh_TW/LC_MESSAGES/django.po @@ -0,0 +1,151 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: Wagtail\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-03-14 23:02+0200\n" +"PO-Revision-Date: 2014-03-14 21:12+0000\n" +"Last-Translator: wdv4758h \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: .\models.py:10 +msgid "Redirect from" +msgstr "重導向起點" + +#: .\models.py:12 +msgid "Permanent" +msgstr "永久" + +#: .\models.py:12 +msgid "" +"Recommended. Permanent redirects ensure search engines forget the old page " +"(the 'Redirect from') and index the new page instead." +msgstr "(推薦) 永久頁面重導向確保搜尋引擎忘記舊頁面(重導向起點),並且改成對新頁面做索引。" + +#: .\models.py:13 +msgid "Redirect to a page" +msgstr "重導向到一個頁面" + +#: .\models.py:14 +msgid "Redirect to any URL" +msgstr "重導向到任何一個 URL" + +#: .\views.py:56 +msgid "Search redirects" +msgstr "搜尋重導向" + +#: .\views.py:69 +msgid "Redirect '{0}' updated." +msgstr "重導向 '{0}' 已更新" + +#: .\views.py:72 +msgid "The redirect could not be saved due to errors." +msgstr "重導向因有錯誤而無法儲存。" + +#: .\views.py:90 +msgid "Redirect '{0}' deleted." +msgstr "重導向 '{0}' 已刪除" + +#: .\views.py:110 +msgid "Redirect '{0} added." +msgstr "重導向 '{0}' 已加入" + +#: .\views.py:113 +msgid "The redirect could not be created due to errors." +msgstr "重導向因有錯誤而無法建立。" + +#: .\templates\wagtailredirects\add.html:3 +#: .\templates\wagtailredirects\add.html:6 +#: .\templates\wagtailredirects\index.html:18 +msgid "Add redirect" +msgstr "增加重導向" + +#: .\templates\wagtailredirects\add.html:14 +#: .\templates\wagtailredirects\edit.html:14 +msgid "Save" +msgstr "儲存" + +#: .\templates\wagtailredirects\confirm_delete.html:4 +#, python-format +msgid "Delete redirect %(title)s" +msgstr "刪除重導向 %(title)s" + +#: .\templates\wagtailredirects\confirm_delete.html:6 +msgid "Delete" +msgstr "刪除" + +#: .\templates\wagtailredirects\confirm_delete.html:10 +msgid "Are you sure you want to delete this redirect?" +msgstr "你確定想刪除這個重導向?" + +#: .\templates\wagtailredirects\confirm_delete.html:13 +msgid "Yes, delete" +msgstr "是的, 刪除" + +#: .\templates\wagtailredirects\edit.html:4 +#, python-format +msgid "Editing %(title)s" +msgstr "編輯 %(title)s" + +#: .\templates\wagtailredirects\edit.html:6 +msgid "Editing" +msgstr "編輯" + +#: .\templates\wagtailredirects\edit.html:15 +msgid "Delete redirect" +msgstr "刪除重導向" + +#: .\templates\wagtailredirects\index.html:3 +#: .\templates\wagtailredirects\index.html:17 +msgid "Redirects" +msgstr "重導向" + +#: .\templates\wagtailredirects\list.html:18 +msgid "To" +msgstr "到" + +#: .\templates\wagtailredirects\list.html:19 +msgid "Type" +msgstr "類型" + +#: .\templates\wagtailredirects\list.html:26 +msgid "Edit this redirect" +msgstr "編輯這個重導向" + +#: .\templates\wagtailredirects\list.html:35 +msgid "primary" +msgstr "主要" + +#: .\templates\wagtailredirects\results.html:5 +#, python-format +msgid "" +"\n" +" There is one match\n" +" " +msgid_plural "" +"\n" +" There are %(counter)s matches\n" +" " +msgstr[0] "\n 有一個符合" +msgstr[1] "\n 有 $(counter)s 個符合" + +#: .\templates\wagtailredirects\results.html:18 +#, python-format +msgid "Sorry, no redirects match \"%(query_string)s\"" +msgstr "對不起,沒有任何重導向符合 \"%(query_string)s\"" + +#: .\templates\wagtailredirects\results.html:21 +#, python-format +msgid "" +"No redirects have been created. Why not add one?" +msgstr "沒有任何已儲存的重導向。為什麼不 增加一個?" From c6f5ebced95f10cc87a373601ceefdc548b973f0 Mon Sep 17 00:00:00 2001 From: dv Date: Sat, 3 May 2014 23:45:33 +0800 Subject: [PATCH 09/57] add zh_TW translation for wagtailsnippets --- .../locale/zh_TW/LC_MESSAGES/django.mo | Bin 0 -> 2370 bytes .../locale/zh_TW/LC_MESSAGES/django.po | 126 ++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 wagtail/wagtailsnippets/locale/zh_TW/LC_MESSAGES/django.mo create mode 100644 wagtail/wagtailsnippets/locale/zh_TW/LC_MESSAGES/django.po diff --git a/wagtail/wagtailsnippets/locale/zh_TW/LC_MESSAGES/django.mo b/wagtail/wagtailsnippets/locale/zh_TW/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..8b44d0230a9f903fa0c0805cf4fc773b30ea07dc GIT binary patch literal 2370 zcma)+?QaxC9LGmMltWMv@gcsLAPpsDdwVCfm+Q5Nr6fd)6;2ypo!i^tcFlG7va{D( zNs|McROG0MO_2hDLK;FKQqzhwZF%PlV`AbfjfwG%w|Bi)_y_pH@9gfiK5WlU?zf-W zx$peuI}ba*?btLyP@YG;g!mQFfVlDq9w_n#LS6tPU>o=bxEUM;g?DF64(g-;_j|+*oCMSq;S_>yg!Y24uR!xi&!&Jc6e}~7|LDKS`(I>Jb@5CpF(Uyh$7Ai zIi#wzp^+PUF30SYJ(Oc9L+NMxI5}i7I%MW4&-;}@#jvSuQk7+y&8V&EJhY~S6`IH+W7MbG++%~PH>mA8;$ zcZY(VFb$RnD;)>P2_z&Zyj|fdmAWQYRSBL`jE;a^T``;pyAqPr81?PYw3*MUuH`;f zn+8?$*l3e7%Q7wAytbahulgUgZf6;JkMaHfnIWhCe$a;L-cz-G8{S(RvbnCvJ9}z< zQ9h@-dq8?D^8=Q)rK76!F0;698gbg|Z9?cc%bAufb@Pm_O0VZLTuPd88tQo~DRqiH zgjhO^G;tc0BL^h;6)7UqNHiX8X_BL|454(K4d^22KXg$k8l#a{<8o`0j1qcN;kJ~t z6oY3K+qB|zP#rkX+7i=fqE>q?(~o1(oHqMAAU863CBvj7Q~Kej`)GI9s`*H>9O^U; zn;FQ7Z#7PB_MsilWfk3MqiIdCIJ4W|Ngk16t2#0ENoGl1M%q;IWyEQ$Pq$Y_iqns@ zRI)eJ;~r+|h-vlnI5oVp&D$ew)T_43Z6V^^xaxd56?6{q<&_>xRc!`|WdFV~ zD)(+4d!@RhT;K!D1nk>D<*Jo|b1%GuK5V(Gy|kYwd+q?NOy<-7NOFPy2I zStu{mUZu=5wfG6T*4 literal 0 HcmV?d00001 diff --git a/wagtail/wagtailsnippets/locale/zh_TW/LC_MESSAGES/django.po b/wagtail/wagtailsnippets/locale/zh_TW/LC_MESSAGES/django.po new file mode 100644 index 000000000..998705768 --- /dev/null +++ b/wagtail/wagtailsnippets/locale/zh_TW/LC_MESSAGES/django.po @@ -0,0 +1,126 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: Wagtail\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-03-10 12:25+0200\n" +"PO-Revision-Date: 2014-02-28 16:07+0000\n" +"Last-Translator: wdv4758h \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: .\templates\wagtailsnippets\chooser\choose.html:2 +msgid "Choose" +msgstr "選擇" + +#: .\templates\wagtailsnippets\edit_handlers\snippet_chooser_panel.html:10 +#, python-format +msgid "Choose another %(snippet_type_name)s" +msgstr "選擇另外一個 %(snippet_type_name)s" + +#: .\templates\wagtailsnippets\edit_handlers\snippet_chooser_panel.html:11 +#, python-format +msgid "Choose %(snippet_type_name)s" +msgstr "選擇 %(snippet_type_name)s" + +#: .\templates\wagtailsnippets\snippets\confirm_delete.html:3 +#, python-format +msgid "Delete %(snippet_type_name)s - %(instance)s" +msgstr "刪除 %(snippet_type_name)s - %(instance)s" + +#: .\templates\wagtailsnippets\snippets\confirm_delete.html:6 +#: .\templates\wagtailsnippets\snippets\edit.html:20 +msgid "Delete" +msgstr "刪除" + +#: .\templates\wagtailsnippets\snippets\confirm_delete.html:10 +#, python-format +msgid "Are you sure you want to delete this %(snippet_type_name)s?" +msgstr "你確定想要刪除這個 %(snippet_type_name)s嗎?" + +#: .\templates\wagtailsnippets\snippets\confirm_delete.html:13 +msgid "Yes, delete" +msgstr "是的,刪除" + +#: .\templates\wagtailsnippets\snippets\create.html:3 +#, python-format +msgid "New %(snippet_type_name)s" +msgstr "新的 %(snippet_type_name)s" + +#: .\templates\wagtailsnippets\snippets\create.html:6 +msgid "New" +msgstr "新建" + +#: .\templates\wagtailsnippets\snippets\create.html:17 +#: .\templates\wagtailsnippets\snippets\edit.html:17 +msgid "Save" +msgstr "儲存" + +#: .\templates\wagtailsnippets\snippets\edit.html:3 +#, python-format +msgid "Editing %(snippet_type_name)s - %(instance)s" +msgstr "編輯 %(snippet_type_name)s - %(instance)s" + +#: .\templates\wagtailsnippets\snippets\edit.html:6 +msgid "Editing" +msgstr "編輯" + +#: .\templates\wagtailsnippets\snippets\index.html:3 +msgid "Snippets" +msgstr "片段" + +#: .\templates\wagtailsnippets\snippets\list.html:8 +msgid "Title" +msgstr "標題" + +#: .\templates\wagtailsnippets\snippets\type_index.html:3 +#, python-format +msgid "Snippets %(snippet_type_name_plural)s" +msgstr "%(snippet_type_name_plural)s 片段" + +#: .\templates\wagtailsnippets\snippets\type_index.html:10 +#, python-format +msgid "Snippets %(snippet_type_name_plural)s" +msgstr "%(snippet_type_name_plural)s 片段" + +#: .\templates\wagtailsnippets\snippets\type_index.html:13 +#, python-format +msgid "Add %(snippet_type_name)s" +msgstr "增加 %(snippet_type_name)s" + +#: .\templates\wagtailsnippets\snippets\type_index.html:23 +#, python-format +msgid "" +"No %(snippet_type_name_plural)s have been created. Why not add one?" +msgstr "" +"沒有任何 %(snippet_type_name_plural)s 片段。為什麼不建立一個?" + +#: .\views\snippets.py:127 +msgid "{snippet_type} '{instance}' created." +msgstr "已建立 {snippet_type} '{instance}'" + +#: .\views\snippets.py:134 +msgid "The snippet could not be created due to errors." +msgstr "片段因有錯誤而無法建立。" + +#: .\views\snippets.py:168 +msgid "{snippet_type} '{instance}' updated." +msgstr "已經更新 {snippet_type} '{instance}'。" + +#: .\views\snippets.py:175 +msgid "The snippet could not be saved due to errors." +msgstr "片段因有錯誤而無法儲存。" + +#: .\views\snippets.py:204 +msgid "{snippet_type} '{instance}' deleted." +msgstr "已刪除 {snippet_type} '{instance}'" From 8719d1ae1f28fcb99ca5a77f33e4d235bc2940f4 Mon Sep 17 00:00:00 2001 From: dv Date: Sat, 3 May 2014 23:56:28 +0800 Subject: [PATCH 10/57] add zh_TW translation for wagtailusers --- .../locale/zh_TW/LC_MESSAGES/django.mo | Bin 0 -> 3045 bytes .../locale/zh_TW/LC_MESSAGES/django.po | 181 ++++++++++++++++++ 2 files changed, 181 insertions(+) create mode 100644 wagtail/wagtailusers/locale/zh_TW/LC_MESSAGES/django.mo create mode 100644 wagtail/wagtailusers/locale/zh_TW/LC_MESSAGES/django.po diff --git a/wagtail/wagtailusers/locale/zh_TW/LC_MESSAGES/django.mo b/wagtail/wagtailusers/locale/zh_TW/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..fb54470cb4d88ffcc11e40a0de3ef0643572e4a1 GIT binary patch literal 3045 zcma)+ZEO@p7{^Bi!QuAza@WDu;i67+l_NpHY@q?Ne^gp|McMu3Nxw+rY z%rnpYpJ$%kpQnuLCTKPgXh5l@B%my z`~@5j{s!I!UIHt@e?h*la-6$953Inr4&?ja1gpU|ko)-pyaW6W4VHjEg3o{xu=pxi4%UI4;C_f-oUpdpr-`gYgBAwm1JL$m6^W3gAQx_`YXB zuDcrKx?Tj4LJ|Y#gK-c)lJw@k1Ruuu8<6k6=Ydy`lGE<>$m@b@;&DIb&2dcgo}UDtLg)Ij zZL0V1M0Nsv5WNT;S40p7;jhO1=ue}Q0(wPjh%lW|*`S)rXjC+Vk=*k23`H0h%?N5S z)nt0H;qG8YeoqaJ8BC|GvKgUfL^PeDDn=O<6`hGvoU%2tVH!SC6Lj2wrrg3vjU-Xg zv34H07d%8|)&0jFT{JasE;}-4L~LO=2=1F?MK2gR8il(foK2j&^hDn#go-7JcQx2|T zQVDz@drr_1Y`!Tei&W7Kda;;wxR~)kniNr8Mdc7xHIoJ-q8f%`A6d*=m_nR`mw7@- z_JIa9H6-h}I%p*IY;{c5ndGAte(pfWK}^T(>NLb!neL;DnaO8Ls3eDF6Va*?omc8B zomncBHlhlYxR2Cp3Ny%ZC?d<5s0SlXe3;R6JzfHF?%2J3T3E%RbBkuIjxjynh--r6 zVxy`QlZ9ltDVi~ZpvtJ(s^!xhl9?hI&>*SPP1ldlv2qfL!cZh92ThCyQ8p%%s1$<_ zjWS)=bX+HQd9ASl&DS$U+49oODR+__S8J!{r7pXkX?oNMP_@|^8r5ZUsQXy$pHp!4CojEcb80wYCED#{ zhpeu5u34nhuJ{t>&D=eyv*+yXeVIg?b!N!^WLxU&b_~Z7J7H&aby@>G#2P-8*}0Ec z-TSaYtOI+kE&Fr3t{L0Md+n}G#0A{upRB}tQ0gw^_PfsQT^rNKwv6rUBKDcSO!5R7 z+dXOxbfwPq+Q(0lOmf(2J7{g~NDXfp```d{r~5v{7VE?&`#=(+(mRr4M|v^?n+YTn z>(Ki2-aQD%YX59(-SF?p4mX_qnS*abh{El^;$Q=DBljyKF_NGsD zTcaa(e>;L8|6}Lq=60UEY`OWUy?!J$niv~N;!JvTA2qM|oMLxBY+j`%l1OG|!&$4V lA6jpe&zxNEJI3q8i6tLMekHy8bb7~Neg!ve_npj-$$xCO64?L% literal 0 HcmV?d00001 diff --git a/wagtail/wagtailusers/locale/zh_TW/LC_MESSAGES/django.po b/wagtail/wagtailusers/locale/zh_TW/LC_MESSAGES/django.po new file mode 100644 index 000000000..f3e0ef3a3 --- /dev/null +++ b/wagtail/wagtailusers/locale/zh_TW/LC_MESSAGES/django.po @@ -0,0 +1,181 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: Wagtail\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-03-14 23:02+0200\n" +"PO-Revision-Date: 2014-03-14 21:12+0000\n" +"Last-Translator: wdv4758h \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: .\forms.py:12 .\forms.py:73 +msgid "Administrator" +msgstr "管理者" + +#: .\forms.py:14 +msgid "If ticked, this user has the ability to manage user accounts." +msgstr "如果已勾選,這個使用者將有權限管理使用者帳號" + +#: .\forms.py:17 .\forms.py:58 +msgid "Email" +msgstr "電子信箱" + +#: .\forms.py:18 .\forms.py:59 +msgid "First Name" +msgstr "名" + +#: .\forms.py:19 .\forms.py:60 +msgid "Last Name" +msgstr "姓" + +#: .\forms.py:46 +msgid "A user with that username already exists." +msgstr "一個使用者已經佔用這個名字" + +#: .\forms.py:47 +msgid "The two password fields didn't match." +msgstr "密碼不符合" + +#: .\forms.py:50 .\templates\wagtailusers\list.html:15 +msgid "Username" +msgstr "使用者名稱" + +#: .\forms.py:53 +msgid "Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "必填,30個字元以内。只允許字母、數字、@/./+/-/_" + +#: .\forms.py:55 +msgid "This value may contain only letters, numbers and @/./+/-/_ characters." +msgstr "這個值只能含有字母、數字、@/./+/-/_" + +#: .\forms.py:63 +msgid "Password" +msgstr "密碼" + +#: .\forms.py:66 +msgid "Leave blank if not changing." +msgstr "如果不修改請留空" + +#: .\forms.py:68 +msgid "Password confirmation" +msgstr "密碼確認" + +#: .\forms.py:70 +msgid "Enter the same password as above, for verification." +msgstr "輸入和上面一樣的密碼用於驗證" + +#: .\forms.py:75 +msgid "Administrators have the ability to manage user accounts." +msgstr "管理者們有管理使用者帳號的權限" + +#: .\templates\wagtailusers\create.html:4 +#: .\templates\wagtailusers\create.html:8 +#: .\templates\wagtailusers\create.html:35 +msgid "Add user" +msgstr "增加使用者" + +#: .\templates\wagtailusers\create.html:12 +#: .\templates\wagtailusers\edit.html:12 +msgid "Account" +msgstr "帳號" + +#: .\templates\wagtailusers\create.html:13 +#: .\templates\wagtailusers\create.html:28 +#: .\templates\wagtailusers\edit.html:13 +msgid "Roles" +msgstr "角色" + +#: .\templates\wagtailusers\edit.html:4 .\templates\wagtailusers\edit.html:8 +msgid "Editing" +msgstr "編輯" + +#: .\templates\wagtailusers\edit.html:30 .\templates\wagtailusers\edit.html:37 +msgid "Save" +msgstr "儲存" + +#: .\templates\wagtailusers\index.html:4 +#: .\templates\wagtailusers\index.html:17 +msgid "Users" +msgstr "使用者" + +#: .\templates\wagtailusers\index.html:18 +msgid "Add a user" +msgstr "增加使用者" + +#: .\templates\wagtailusers\list.html:7 +msgid "Name" +msgstr "名字" + +#: .\templates\wagtailusers\list.html:22 +msgid "Level" +msgstr "等級" + +#: .\templates\wagtailusers\list.html:23 +msgid "Status" +msgstr "狀態" + +#: .\templates\wagtailusers\list.html:36 +msgid "Admin" +msgstr "管理" + +#: .\templates\wagtailusers\list.html:37 +msgid "Active" +msgstr "啟用" + +#: .\templates\wagtailusers\list.html:37 +msgid "Inactive" +msgstr "未啟用" + +#: .\templates\wagtailusers\results.html:5 +#, python-format +msgid "" +"\n" +" There is one match\n" +" " +msgid_plural "" +"\n" +" There are %(counter)s matches\n" +" " +msgstr[0] "\n 有一個符合" +msgstr[1] "\n 有 $(counter)s 個符合" + +#: .\templates\wagtailusers\results.html:18 +#, python-format +msgid "Sorry, no users match \"%(query_string)s\"" +msgstr "對不起,沒有任何使用者符合 \"%(query_string)s\"" + +#: .\templates\wagtailusers\results.html:21 +#, python-format +msgid "" +"There are no users configured. Why not add some?" +msgstr "沒有使用者. 為什麼不 增加一個?" + +#: .\views\users.py:21 .\views\users.py:28 +msgid "Search users" +msgstr "搜尋使用者" + +#: .\views\users.py:75 +msgid "User '{0}' created." +msgstr "使用者 '{0}' 已建立" + +#: .\views\users.py:78 +msgid "The user could not be created due to errors." +msgstr "使用者因有錯誤而無法建立。" + +#: .\views\users.py:94 +msgid "User '{0}' updated." +msgstr "使用者 '{0}' 已更新" + +#: .\views\users.py:97 +msgid "The user could not be saved due to errors." +msgstr "使用者因有錯誤而無法儲存。" From d933965acc013bcc8ff2c5c0bfb371525eeaa164 Mon Sep 17 00:00:00 2001 From: dv Date: Sun, 4 May 2014 00:12:45 +0800 Subject: [PATCH 11/57] add zh_TW translation for wagtailcore --- .../locale/zh_TW/LC_MESSAGES/django.mo | Bin 0 -> 1819 bytes .../locale/zh_TW/LC_MESSAGES/django.po | 64 ++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 wagtail/wagtailcore/locale/zh_TW/LC_MESSAGES/django.mo create mode 100644 wagtail/wagtailcore/locale/zh_TW/LC_MESSAGES/django.po diff --git a/wagtail/wagtailcore/locale/zh_TW/LC_MESSAGES/django.mo b/wagtail/wagtailcore/locale/zh_TW/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..db50be133f5f69436831d6c992333d6ee7e396e5 GIT binary patch literal 1819 zcma)6U2_vv7(Oa~W%R~tFWws`$>65jS|Afd9r+lTp#zp67wRyZ{VC>_A=~ym|B0rj==tceF)q86k{RaHQ*}nM_>|o>}kg0z~6wof&T(G19v~e z*n9B#44B6I?;98!2X13Yf4UK)3PXU*cpqH!;h7?D_zP8hYaisndc7W zg)42Nz+HqHk}`s9ArUjd$>=BHwsa~akUh^$heX+C`-;*OwqeC6e1IEHI!`<8oN05~ z<(M4RDq)hQw0Mk?ic61%Q7pohPy=~LisB$8r5sUq!K7^38Bvb0{YDP|t8jLJD{o|w zf?QGHc(!u`;-G6&TqiS26;UFa^NeC#%%6 z##j<X9>Ck*QLza1ztITLM#mVK|rc|Y;bg`7O%rrZchkDS$fUA8}`SpbDMd6Z)2on5rJyYq(NNI)?39 zh7?YM%9)ALEt}$bdUNgRogAdMl=N@G-OiQJmzLy40er^xjO~0(emJIwwhLS0@MuXi zo*>CTmP17gquWa9yy3W9ZabLVrNtlnsoGiYXglq+P)8;~@sueaRZ7q&`NPRWq5W3L zF)VGDa0+gM>|*cL-8Q_H`j6Z6ts&+uobcyb-Ri9W?M+IS98SUcQ=MzK|5=^JrdO>6 zckcvCv)--A&TJ#7f8l+8w|&3q-}%OGec743?)`kb?|`UBUjdb3?X3S@J;5U0%+2oc zl_-V%dds_2^Hv-FnXkQ>n%6uPCVz3ZJ3kFSQY>00yYn}LtM|OtVo;swEIjaL7Zsz0 zW^nzS->SA(zVe&DuFxwO3Ai4{moa{<_v1^(CQ5 zFVng!+`fN0ICU2a`HiV4>lgMW?*%gt(U$slsQO<0w6}Z?4Ev@3$F*JGG)2&_fAWXU zjWgcWX3&@pS~YL#7V<_JM(NcTP)ZG`)(FmC^rz~o<1ySl>Rg%cOFR&ydL{U&j!=L3 rYQF&M-%AMKH&?yodVjY&Kj+P%#JSG=Vw464;PR4p|6Z_EQ&avA=SIbD literal 0 HcmV?d00001 diff --git a/wagtail/wagtailcore/locale/zh_TW/LC_MESSAGES/django.po b/wagtail/wagtailcore/locale/zh_TW/LC_MESSAGES/django.po new file mode 100644 index 000000000..a5da59aff --- /dev/null +++ b/wagtail/wagtailcore/locale/zh_TW/LC_MESSAGES/django.po @@ -0,0 +1,64 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: Wagtail\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-03-10 12:24+0200\n" +"PO-Revision-Date: 2014-02-28 16:07+0000\n" +"Last-Translator: wdv4758h \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: .\models.py:36 +msgid "" +"Set this to something other than 80 if you need a specific port number to " +"appear in URLs (e.g. development on port 8000). Does not affect request " +"handling (so port forwarding still works)." +msgstr "" +"如果你需要指定 port,請選擇一個非 80 的 port number (例如: 開發中用 8000 port)。 不影響 request 處理" +" (port forwarding 仍然有效)" + +#: .\models.py:38 +msgid "" +"If true, this site will handle requests for all other hostnames that do not " +"have a site entry of their own" +msgstr "" +"如果這是 Ture 的話,這個網站將處理其他沒有自己網站的 hostname 的 request。" + +#: .\models.py:163 +msgid "The page title as you'd like it to be seen by the public" +msgstr "頁面標題 (你想讓外界看到的)" + +#: .\models.py:164 +msgid "" +"The name of the page as it will appear in URLs e.g http://domain.com/blog/" +"[my-slug]/" +msgstr "一個出現在 URL 的名字,例如 http://domain.com/blog/[my-slug]/" + +#: .\models.py:173 +msgid "Page title" +msgstr "頁面標題" + +#: .\models.py:173 +msgid "" +"Optional. 'Search Engine Friendly' title. This will appear at the top of the " +"browser window." +msgstr "(可選) '搜尋引擎友善' 標題。 這會顯示在瀏覽器的視窗最上方" + +#: .\models.py:174 +msgid "" +"Whether a link to this page will appear in automatically generated menus" +msgstr "是否在自動生成的 Menu 裡顯示一個連結到此頁面" + +#: .\models.py:418 +#, python-format +msgid "name '%s' (used in subpage_types list) is not defined." +msgstr "'%s' (用於子頁面類型列表) 沒有被建立。" From a2e72044ecaeb9943a03cd3568e6b9e23d9202ef Mon Sep 17 00:00:00 2001 From: dv Date: Sun, 4 May 2014 10:17:43 +0800 Subject: [PATCH 12/57] update some words --- .../locale/zh_TW/LC_MESSAGES/django.mo | Bin 13960 -> 13960 bytes .../locale/zh_TW/LC_MESSAGES/django.po | 12 ++++++------ .../locale/zh_TW/LC_MESSAGES/django.mo | Bin 2328 -> 2328 bytes .../locale/zh_TW/LC_MESSAGES/django.po | 4 ++-- .../locale/zh_TW/LC_MESSAGES/django.mo | Bin 2629 -> 2629 bytes .../locale/zh_TW/LC_MESSAGES/django.po | 6 +++--- .../locale/zh_TW/LC_MESSAGES/django.mo | Bin 2636 -> 2636 bytes .../locale/zh_TW/LC_MESSAGES/django.po | 4 ++-- .../locale/zh_TW/LC_MESSAGES/django.mo | Bin 3859 -> 3859 bytes .../locale/zh_TW/LC_MESSAGES/django.po | 6 +++--- .../locale/zh_TW/LC_MESSAGES/django.mo | Bin 2370 -> 2370 bytes .../locale/zh_TW/LC_MESSAGES/django.po | 2 +- .../locale/zh_TW/LC_MESSAGES/django.mo | Bin 3045 -> 3045 bytes .../locale/zh_TW/LC_MESSAGES/django.po | 6 +++--- 14 files changed, 20 insertions(+), 20 deletions(-) diff --git a/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.mo b/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.mo index b7bddb8ff7290512d555145b3db2f3252b5a09d6..a00aa643baf9cd7be4bc221dfece36119c11d1e0 100644 GIT binary patch delta 109 zcmeCk?a1A5QH|}{v<*)e&71s3UBZ(A!hW)&;b}wn%h|i1uAT5?|H9|%Hlj#8T{7)u m^NN=Zi=S_u0F?kLe7T_U<=jP3{$>mHr#w)TH!GW@G64XSv_jDU delta 109 zcmeCk?a1A5QH|~CqIpld7EJ!5F5$@lVL#c?@U)@(lE}8bS ldBw|y#m~1+fJy)rzFg4wa_%B1f3t=9Qy!?vo0UycnE-J;LL&eG diff --git a/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.po b/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.po index e6f8e743b..f4d70b60e 100644 --- a/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.po +++ b/wagtail/wagtailadmin/locale/zh_TW/LC_MESSAGES/django.po @@ -222,7 +222,7 @@ msgstr "選擇一個頁面" #: .\templates\wagtailadmin\chooser\email_link.html:2 msgid "Add an email link" -msgstr "增加一個電子信箱" +msgstr "新增一個電子信箱" #: .\templates\wagtailadmin\chooser\email_link.html:14 #: .\templates\wagtailadmin\chooser\external_link.html:14 @@ -231,7 +231,7 @@ msgstr "插入一個連結" #: .\templates\wagtailadmin\chooser\external_link.html:2 msgid "Add an external link" -msgstr "增加一個外部連結" +msgstr "新增一個外部連結" #: .\templates\wagtailadmin\edit_handlers\chooser_panel.html:20 msgid "Clear choice" @@ -605,7 +605,7 @@ msgstr "瀏覽%(title)s" #: .\templates\wagtailadmin\pages\list.html:53 #: .\templates\wagtailadmin\pages\list.html:194 msgid "Add child page" -msgstr "增加子頁面" +msgstr "新增子頁面" #: .\templates\wagtailadmin\pages\list.html:94 msgid "Disable ordering of child pages" @@ -644,11 +644,11 @@ msgstr "瀏覽 '%(title)s' 的子頁面" #: .\templates\wagtailadmin\pages\list.html:230 #, python-format msgid "Add a child page to '%(title)s'" -msgstr "增加子頁面至 '%(title)s'" +msgstr "新增子頁面至 '%(title)s'" #: .\templates\wagtailadmin\pages\list.html:230 msgid "Add subpage" -msgstr "增加子頁面" +msgstr "新增子頁面" #: .\templates\wagtailadmin\pages\list.html:239 msgid "No pages have been created." @@ -657,7 +657,7 @@ msgstr "沒有已儲存的頁面" #: .\templates\wagtailadmin\pages\list.html:239 #, python-format msgid "Why not add one?" -msgstr "為什麼不 增加一個頁面呢?" +msgstr "為什麼不 新增一個頁面呢?" #: .\templates\wagtailadmin\pages\move_choose_destination.html:3 #, python-format diff --git a/wagtail/wagtaildocs/locale/zh_TW/LC_MESSAGES/django.mo b/wagtail/wagtaildocs/locale/zh_TW/LC_MESSAGES/django.mo index 195d80cc4fff29c4d1322e3a15dd2f6272c71709..65fb219cc8e64b2997e3f3966eb9e1ac6b73ea55 100644 GIT binary patch delta 38 rcmbOsG(%{^Z8phg(>6R^H1Eldh9|rCKAYD5WcM}(h|uOQY${9uuv!*G delta 38 rcmbOsG(%{^Z8piLi{?G;TJU5?!;{^6pG|9jvU?i?L}>FDHWelStdSN9 diff --git a/wagtail/wagtaildocs/locale/zh_TW/LC_MESSAGES/django.po b/wagtail/wagtaildocs/locale/zh_TW/LC_MESSAGES/django.po index b2d46ac09..f5bff5468 100644 --- a/wagtail/wagtaildocs/locale/zh_TW/LC_MESSAGES/django.po +++ b/wagtail/wagtaildocs/locale/zh_TW/LC_MESSAGES/django.po @@ -80,11 +80,11 @@ msgstr "修改文件:" #: .\templates\wagtaildocs\documents\add.html:4 #: .\templates\wagtaildocs\documents\index.html:17 msgid "Add a document" -msgstr "增加一份文件" +msgstr "新增一份文件" #: .\templates\wagtaildocs\documents\add.html:15 msgid "Add document" -msgstr "增加文件" +msgstr "新增文件" #: .\templates\wagtaildocs\documents\confirm_delete.html:3 #, python-format diff --git a/wagtail/wagtailimages/locale/zh_TW/LC_MESSAGES/django.mo b/wagtail/wagtailimages/locale/zh_TW/LC_MESSAGES/django.mo index 203f1dd38efbc9a4c3d67359736b6bb2ea88142c..284cefcb2bb6000ce4f01e555420500b30599d67 100644 GIT binary patch delta 60 zcmX>qa#UnP6}#lKX&as{n)hT!!_$WDr*oz~?`&s)2yLFsK9@-pMS9{Q8~sE(djqa#UnP6}#lqMf09^EqJn{;b}wn(>c?gceXP?gf>rRpUWhQB0X`Djeeq?Jp%v| Cj3FTa diff --git a/wagtail/wagtailimages/locale/zh_TW/LC_MESSAGES/django.po b/wagtail/wagtailimages/locale/zh_TW/LC_MESSAGES/django.po index 0fd9bc93c..5db580a36 100644 --- a/wagtail/wagtailimages/locale/zh_TW/LC_MESSAGES/django.po +++ b/wagtail/wagtailimages/locale/zh_TW/LC_MESSAGES/django.po @@ -94,11 +94,11 @@ msgstr "更改圖片:" #: .\templates\wagtailimages\images\add.html:4 #: .\templates\wagtailimages\images\index.html:19 msgid "Add an image" -msgstr "增加一個圖片" +msgstr "新增一個圖片" #: .\templates\wagtailimages\images\add.html:15 msgid "Add image" -msgstr "增加圖片" +msgstr "新增圖片" #: .\templates\wagtailimages\images\add.html:25 #: .\templates\wagtailimages\images\edit.html:33 @@ -143,7 +143,7 @@ msgstr "對不起,沒有任何圖片符合 \"%(query_string)s\"" msgid "" "You've not uploaded any images. Why not add one now?" -msgstr "沒有任何上傳的圖片。為什麼不 增加一個呢?" +msgstr "沒有任何上傳的圖片。為什麼不 新增一個呢?" #: .\views\images.py:29 .\views\images.py:40 msgid "Search images" diff --git a/wagtail/wagtailredirects/locale/zh_TW/LC_MESSAGES/django.mo b/wagtail/wagtailredirects/locale/zh_TW/LC_MESSAGES/django.mo index 03ae1357d3b47d082a6e62f81ed71572010985c6..b5f8e50b38d25e406e2fdd36c63568608bb08e17 100644 GIT binary patch delta 30 hcmX>jazjazte+ diff --git a/wagtail/wagtailredirects/locale/zh_TW/LC_MESSAGES/django.po b/wagtail/wagtailredirects/locale/zh_TW/LC_MESSAGES/django.po index fd0a433fe..0d5079b5c 100644 --- a/wagtail/wagtailredirects/locale/zh_TW/LC_MESSAGES/django.po +++ b/wagtail/wagtailredirects/locale/zh_TW/LC_MESSAGES/django.po @@ -67,7 +67,7 @@ msgstr "重導向因有錯誤而無法建立。" #: .\templates\wagtailredirects\add.html:6 #: .\templates\wagtailredirects\index.html:18 msgid "Add redirect" -msgstr "增加重導向" +msgstr "新增重導向" #: .\templates\wagtailredirects\add.html:14 #: .\templates\wagtailredirects\edit.html:14 @@ -148,4 +148,4 @@ msgstr "對不起,沒有任何重導向符合 \"%(query_string)s\"" msgid "" "No redirects have been created. Why not add one?" -msgstr "沒有任何已儲存的重導向。為什麼不 增加一個?" +msgstr "沒有任何已儲存的重導向。為什麼不 新增一個?" diff --git a/wagtail/wagtailsearch/locale/zh_TW/LC_MESSAGES/django.mo b/wagtail/wagtailsearch/locale/zh_TW/LC_MESSAGES/django.mo index b5c01463c7ac9ae52ad17a20e7a43403d5c541f5..038c04394173b1f0154084b29af300223ac75f6c 100644 GIT binary patch delta 63 ycmbO%H(74ORc@na(>6R^H1GNL6)zfEpKsdtvT+9kLJJiL?(6s delta 63 zcmbO%H(74ORc@oFi{?G;TJU`PiWd#7&o}LR*|>uNBJ^z9hUc?dut;oX=iy-n0N(&6 A9{>OV diff --git a/wagtail/wagtailsearch/locale/zh_TW/LC_MESSAGES/django.po b/wagtail/wagtailsearch/locale/zh_TW/LC_MESSAGES/django.po index d001653b6..f322e51b3 100644 --- a/wagtail/wagtailsearch/locale/zh_TW/LC_MESSAGES/django.po +++ b/wagtail/wagtailsearch/locale/zh_TW/LC_MESSAGES/django.po @@ -34,7 +34,7 @@ msgstr "" #: .\templates\wagtailsearch\editorspicks\add.html:3 #: .\templates\wagtailsearch\editorspicks\add.html:5 msgid "Add editor's pick" -msgstr "增加編者精選" +msgstr "新增編者精選" #: .\templates\wagtailsearch\editorspicks\add.html:9 msgid "" @@ -94,7 +94,7 @@ msgstr "編者精選" #: .\templates\wagtailsearch\editorspicks\index.html:18 msgid "Add new editor's pick" -msgstr "增加新的編者精選" +msgstr "新增新的編者精選" #: .\templates\wagtailsearch\editorspicks\list.html:8 msgid "Search term(s)" @@ -156,7 +156,7 @@ msgstr "編者精選" #: .\templates\wagtailsearch\editorspicks\includes\editorspicks_formset.html:14 msgid "Add recommended page" -msgstr "增加推薦頁面" +msgstr "新增推薦頁面" #: .\templates\wagtailsearch\queries\chooser\chooser.html:2 msgid "Popular search terms" diff --git a/wagtail/wagtailsnippets/locale/zh_TW/LC_MESSAGES/django.mo b/wagtail/wagtailsnippets/locale/zh_TW/LC_MESSAGES/django.mo index 8b44d0230a9f903fa0c0805cf4fc773b30ea07dc..d3f5578db87230060a85c666cc1216ed90ffffb1 100644 GIT binary patch delta 23 fcmX>kbVz7J0vp@2X&as{nm5^jS$uOX+fgO}eozVk delta 23 fcmX>kbVz7J0vp@YMf09^Etu@UEWWvx?I;rfeG3WW diff --git a/wagtail/wagtailsnippets/locale/zh_TW/LC_MESSAGES/django.po b/wagtail/wagtailsnippets/locale/zh_TW/LC_MESSAGES/django.po index 998705768..e89aca887 100644 --- a/wagtail/wagtailsnippets/locale/zh_TW/LC_MESSAGES/django.po +++ b/wagtail/wagtailsnippets/locale/zh_TW/LC_MESSAGES/django.po @@ -94,7 +94,7 @@ msgstr "%(snippet_type_name_plural)s 片段" #: .\templates\wagtailsnippets\snippets\type_index.html:13 #, python-format msgid "Add %(snippet_type_name)s" -msgstr "增加 %(snippet_type_name)s" +msgstr "新增 %(snippet_type_name)s" #: .\templates\wagtailsnippets\snippets\type_index.html:23 #, python-format diff --git a/wagtail/wagtailusers/locale/zh_TW/LC_MESSAGES/django.mo b/wagtail/wagtailusers/locale/zh_TW/LC_MESSAGES/django.mo index fb54470cb4d88ffcc11e40a0de3ef0643572e4a1..59297ccaa21aadd3e04eb727bd392f5d972e8e66 100644 GIT binary patch delta 46 vcmaDV{#1O!bq=v-(>6R^H1EmY{m-YYc+t?x0O4M?0 delta 46 vcmaDV{#1O!bq=woi{?G;TJU7={^wIxyl7};fbciJ%(query_string)s\"" msgid "" "There are no users configured. Why not add some?" -msgstr "沒有使用者. 為什麼不 增加一個?" +msgstr "沒有使用者. 為什麼不 新增一個?" #: .\views\users.py:21 .\views\users.py:28 msgid "Search users" From 21dfbbfee9d4b89f40546859bd38408d77669139 Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Wed, 7 May 2014 14:26:04 -0400 Subject: [PATCH 13/57] moar docs --- docs/building_your_site.rst | 247 +++++++++++++++++++++++++++++++++++- 1 file changed, 246 insertions(+), 1 deletion(-) diff --git a/docs/building_your_site.rst b/docs/building_your_site.rst index b506f67f2..0d1eed85c 100644 --- a/docs/building_your_site.rst +++ b/docs/building_your_site.rst @@ -1,6 +1,251 @@ Building your site ================== +Site +~~~~ + +Django's built-in admin interface provides the way to map a "site" (hostname or domain) to the root of a wagtail tree. Access this by going to "/django-admin/" and then "Home › Wagtailcore › Sites." To try out a development site, add a single site with the hostname ``localhost`` at port ``8000`` and map it to one of the pieces of content you have created.. + +Model Design +~~~~~~~~~~~~ + +Wagtail manages content internally as a tree of pages. Each node in the tree is an instance of a Django model which subclasses the Wagtail ``Page`` class. You define the structure and interrelationships of your Wagtail site by coding these models and then publishing pages which use the models through the Wagtail admin interface. + +``Page`` uses Django's model interface, so you can include any field type and field options that Django allows. Wagtail provides some fields and editing handlers that simplify data entry in the Wagtail admin interface, so you may want to keep those in mind when deciding what properties to add to your models in addition to those already provided by ``Page``. + +Built-in Properties of the Page Class +------------------------------------- + +Wagtail provides some properties in the Page class which are common to most webpages. Since you'll be subclassing ``Page``, you don't have to worry about implementing them. + +Public Properties Suitable for Inclusion in Templates +````````````````````````````````````````````````````` +``title`` (required) + Human-readable title for the content + +``slug`` (required) + Machine-readable URL component for this piece of content. The name of the page as it will appear in URLs e.g http://domain.com/blog/[my-slug]/ + +``seo_title`` + Alternate SEO-crafted title which overrides the normal title for use in the of a page + +``search_description`` + A SEO-crafted description of the content, used in both internal search indexing and for the meta description read by search engines + +Private Properties Meant for Use in the Wagtail Admin +````````````````````````````````````````````````````` +``show_in_menus`` + Boolean (checkbox) - Whether a link to this page will appear in automatically generated menus")) + +``live`` + Boolean (content status selectors) - whether the page is in a published, public-visible state + +``has_unpublished_changes`` + Boolean (content status selectors) - whether the page is in a draft state + +``owner`` + User who owns the page + +Internal Properties Which Describe The Model Instance +````````````````````````````````````````````````````` +``content_type`` + ??? Used to keep track of class names + +``url_path`` + The full URL path, including the slugs of all parents going back to the site root. Whenever a slug is changed in the tree, all of the node's descendants are updated with the new path. + +Introduction to Trees +--------------------- + +If you're unfamiliar with trees as an abstract data type, you might want to review the concepts involved: +http://en.wikipedia.org/wiki/Tree_(data_structure) + +As a web developer, though, you probably already have a good understanding of trees as filesystem directories or paths. Wagtail pages can create the same structure, as each page in the tree has its own URL path, like so: + + / + people/ + nien-nunb/ + laura-roslin/ + events/ + captain-picard-day/ + winter-wrap-up/ + +The Wagtail admin interface uses the tree to organize content for editing, letting you navigate up and down levels in the tree through its Explorer menu. This method of organization is a good place to start in thinking about your own Wagtail models. + + +Nodes and Leaves +---------------- + +It might be handy to think of the Page-derived models you want to create as being one of two node types: parents and leaves. + +Parents +``````` +Parent nodes on the Wagtail tree probably want to organize and display a browsable index of their descendents. A blog, for instance, needs a way to show a list of individual posts. + +A Parent node could provide its own function returning its descendant objects. + + class EventPageIndex(Page): + ... + def events(self): + # Get list of event pages that are descendants of this page + events = EventPage.objects.filter( + live=True, + path__startswith=self.path + ) + return events + +This example makes sure to limit the returned objects to pieces of content which make sense, specifically ones which have been published through Wagtail's admin interface (live=True) and are descendants of this node. Wagtail will allow the "illogical" placement of child nodes under a parent, so it's necessary for a parent model to index only those children which make sense. + +Leaves +`````` +Leaves are the pieces of content itself, a page which is consumable, and might just consist of a bunch of properties. A blog page leaf might have some body text and an image. A person page leaf might have a photo, a name, and an address. + +It might be helpful for a leaf to provide a way to back up along the tree to a parent, such as in the case of breadcrumbs navigation. The tree might also be deep enough that a leaf's parent won't be included in general site navigation. + +The model for the leaf could provide a function that traverses the tree in the opposite direction and returns an appropriate ancestor. + + class BlogPage(Page): + ... + def blog_index(self): + # Find blog index in ancestors + for ancestor in reversed(self.get_ancestors()): + if isinstance(ancestor.specific, BlogIndexPage): + return ancestor + + # No ancestors are blog indexes, just return first blog index in database + return BlogIndexPage.objects.first() + +Since Wagtail doesn't limit what Page-derived classes can be assigned as parents and children, the reverse tree traversal needs to accommodate cases which might not be expected, such as the lack of a "logical" parent to a leaf. + +Other Relationships +``````````````````` +Your Page-derived models might have other interrelationships which extend the basic Wagtail tree or depart from it entirely. You could provide functions to navigate between siblings, such as a "Next Post" link on a blog page(post->post->post). It might make sense for subtrees to interrelate, such as in a discussion forum (forum->post->replies) Skipping across the hierarchy might make sense, too, as all objects of a certain model class might interrelate regardless of their ancestors (events = EventPage.objects.all). Since there's no restriction on the combination of model classes that can be used at any point in the tree, and it's largely up to the models to define their interrelations, the possibilities are really endless. + +Advanced +-------- + + custom serve methods + iCal + JSON + + custom route methods + + ParentalKey for storing groups of stuff to a Page-thing + + ClusterTaggableManager for tagging + + Orderable + Provides an abstract group of properties for ordering a collection of stuff + + Using or subclassing the site model? + + +Wagtail Admin +~~~~~~~~~~~~~ + +Fields & Edit Handlers +---------------------- + + RichTextField + + Image + + FieldPanel + + MultiFieldPanel + + InlinePanel + + PageChooserPanel + + ImageChooserPanel + + DocumentChooserPanel + +Snippets +-------- + +Registering and using template tags? + + + +Templates +~~~~~~~~~ + +Location +-------- + Wagtail looks for templates matching your models in... + +Self +---- + Without a custom rendering function, a + +Tags Provided by Wagtail +------------------------ + pageurl + Loaded into a template with + {% load pageurl %} + Used like + + Given a Page-derived class, outputs a page's URL as relative (/foo/bar/) if it's within the same site as the current page, or absolute (http://example.com/foo/bar/) if not. + slugurl + Loaded into a template with + {% load slugurl %} + Used like + + Returns the URL for the page that has the given slug. Like pageurl, will try to provide a relative link if possible, but will default to an absolute link if on a different site. + wagtailuserbar + Loaded into a template with + {% load wagtailuserbar %} + Used like + {% wagtailuserbar %} + This tag provides a Wagtail icon and flyout menu on the top-right of a page for a logged-in user with editing capabilities, with the option of editing the current Page-derived object or adding a new sibling object. + image + Loaded with + {% load image_tags %} + Used with + {% image self.photo max-320x200 %} + {% image self.photo max-320x200 as img %} + This template tag provides a way to process an image with a method and dimensions + + 'max': 'resize_to_max', + 'min': 'resize_to_min', + 'width': 'resize_to_width', + 'height': 'resize_to_height', + 'fill': 'resize_to_fill', + + +Filters Provided by Wagtail +--------------------------- + rich_text + Loaded into template with + {% load rich_text %} + Used with + {{ body|richtext }} + This filter is required for use with any RichTextField, because it will expand internal shorthand references to embeds and links made in the Wagtail editor into fully-baked HTML ready for display. + + +Advanced Wagtail +~~~~~~~~~~~~~~~~ + + replacing image processing backend + + custom image processing methods? + + wagtail user bar custom CSS option? + + + + + + + + + + +Example Site +~~~~~~~~~~~~ + Serafeim Papastefanos has written a comprehensive tutorial on creating a site from scratch in Wagtail; for the time being, this is our recommended resource: -`spapas.github.io/2014/02/13/wagtail-tutorial/ `_ \ No newline at end of file +`spapas.github.io/2014/02/13/wagtail-tutorial/ `_ From 037a77da8adf26e549111dcac21cec20ec0d32f3 Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Wed, 7 May 2014 14:28:20 -0400 Subject: [PATCH 14/57] moar docs --- docs/building_your_site.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/building_your_site.rst b/docs/building_your_site.rst index 0d1eed85c..c3a01d270 100644 --- a/docs/building_your_site.rst +++ b/docs/building_your_site.rst @@ -24,7 +24,7 @@ Public Properties Suitable for Inclusion in Templates Human-readable title for the content ``slug`` (required) - Machine-readable URL component for this piece of content. The name of the page as it will appear in URLs e.g http://domain.com/blog/[my-slug]/ + Machine-readable URL component for this piece of content. The name of the page as it will appear in URLs e.g ``http://domain.com/blog/[my-slug]/`` ``seo_title`` Alternate SEO-crafted title which overrides the normal title for use in the of a page From 1bd49f85e1c75d431c42bb9efea538ef428e3db2 Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Wed, 7 May 2014 14:31:48 -0400 Subject: [PATCH 15/57] moar docs --- docs/building_your_site.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/building_your_site.rst b/docs/building_your_site.rst index c3a01d270..36d264048 100644 --- a/docs/building_your_site.rst +++ b/docs/building_your_site.rst @@ -27,7 +27,7 @@ Public Properties Suitable for Inclusion in Templates Machine-readable URL component for this piece of content. The name of the page as it will appear in URLs e.g ``http://domain.com/blog/[my-slug]/`` ``seo_title`` - Alternate SEO-crafted title which overrides the normal title for use in the of a page + Alternate SEO-crafted title which overrides the normal title for use in the ```` of a page ``search_description`` A SEO-crafted description of the content, used in both internal search indexing and for the meta description read by search engines @@ -60,7 +60,7 @@ Introduction to Trees If you're unfamiliar with trees as an abstract data type, you might want to review the concepts involved: http://en.wikipedia.org/wiki/Tree_(data_structure) -As a web developer, though, you probably already have a good understanding of trees as filesystem directories or paths. Wagtail pages can create the same structure, as each page in the tree has its own URL path, like so: +As a web developer, though, you probably already have a good understanding of trees as filesystem directories or paths. Wagtail pages can create the same structure, as each page in the tree has its own URL path, like so:: / people/ @@ -82,7 +82,7 @@ Parents ``````` Parent nodes on the Wagtail tree probably want to organize and display a browsable index of their descendents. A blog, for instance, needs a way to show a list of individual posts. -A Parent node could provide its own function returning its descendant objects. +A Parent node could provide its own function returning its descendant objects. :: class EventPageIndex(Page): ... @@ -102,7 +102,7 @@ Leaves are the pieces of content itself, a page which is consumable, and might j It might be helpful for a leaf to provide a way to back up along the tree to a parent, such as in the case of breadcrumbs navigation. The tree might also be deep enough that a leaf's parent won't be included in general site navigation. -The model for the leaf could provide a function that traverses the tree in the opposite direction and returns an appropriate ancestor. +The model for the leaf could provide a function that traverses the tree in the opposite direction and returns an appropriate ancestor.:: class BlogPage(Page): ... From b614781e9cd3198429696f170fd8ba9867ede2fc Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Wed, 7 May 2014 14:35:38 -0400 Subject: [PATCH 16/57] moar docs --- docs/building_your_site.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/building_your_site.rst b/docs/building_your_site.rst index 36d264048..c3289958b 100644 --- a/docs/building_your_site.rst +++ b/docs/building_your_site.rst @@ -82,7 +82,7 @@ Parents ``````` Parent nodes on the Wagtail tree probably want to organize and display a browsable index of their descendents. A blog, for instance, needs a way to show a list of individual posts. -A Parent node could provide its own function returning its descendant objects. :: +A Parent node could provide its own function returning its descendant objects. :: python class EventPageIndex(Page): ... @@ -102,7 +102,7 @@ Leaves are the pieces of content itself, a page which is consumable, and might j It might be helpful for a leaf to provide a way to back up along the tree to a parent, such as in the case of breadcrumbs navigation. The tree might also be deep enough that a leaf's parent won't be included in general site navigation. -The model for the leaf could provide a function that traverses the tree in the opposite direction and returns an appropriate ancestor.:: +The model for the leaf could provide a function that traverses the tree in the opposite direction and returns an appropriate ancestor. :: python class BlogPage(Page): ... From af881e07890f0481882693d45635c607d5ebf322 Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Wed, 7 May 2014 14:36:56 -0400 Subject: [PATCH 17/57] moar docs --- docs/building_your_site.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/building_your_site.rst b/docs/building_your_site.rst index c3289958b..0f1ed7e19 100644 --- a/docs/building_your_site.rst +++ b/docs/building_your_site.rst @@ -82,8 +82,9 @@ Parents ``````` Parent nodes on the Wagtail tree probably want to organize and display a browsable index of their descendents. A blog, for instance, needs a way to show a list of individual posts. -A Parent node could provide its own function returning its descendant objects. :: python +A Parent node could provide its own function returning its descendant objects. +.. code-block:: python class EventPageIndex(Page): ... def events(self): From 89d774da76b6f3ae3c64e616e7ecc12fb6c4b4d8 Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Wed, 7 May 2014 14:39:07 -0400 Subject: [PATCH 18/57] moar docs --- docs/building_your_site.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/building_your_site.rst b/docs/building_your_site.rst index 0f1ed7e19..36d264048 100644 --- a/docs/building_your_site.rst +++ b/docs/building_your_site.rst @@ -82,9 +82,8 @@ Parents ``````` Parent nodes on the Wagtail tree probably want to organize and display a browsable index of their descendents. A blog, for instance, needs a way to show a list of individual posts. -A Parent node could provide its own function returning its descendant objects. +A Parent node could provide its own function returning its descendant objects. :: -.. code-block:: python class EventPageIndex(Page): ... def events(self): @@ -103,7 +102,7 @@ Leaves are the pieces of content itself, a page which is consumable, and might j It might be helpful for a leaf to provide a way to back up along the tree to a parent, such as in the case of breadcrumbs navigation. The tree might also be deep enough that a leaf's parent won't be included in general site navigation. -The model for the leaf could provide a function that traverses the tree in the opposite direction and returns an appropriate ancestor. :: python +The model for the leaf could provide a function that traverses the tree in the opposite direction and returns an appropriate ancestor.:: class BlogPage(Page): ... From 1aa04c277d44dd8ee1c03d6a829a11588db955e3 Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Thu, 8 May 2014 00:11:47 -0400 Subject: [PATCH 19/57] moar docs --- docs/building_your_site.rst | 348 +++++++++++++++++++++++------------- 1 file changed, 224 insertions(+), 124 deletions(-) diff --git a/docs/building_your_site.rst b/docs/building_your_site.rst index 36d264048..9dd98ecfc 100644 --- a/docs/building_your_site.rst +++ b/docs/building_your_site.rst @@ -1,13 +1,10 @@ Building your site ================== -Site -~~~~ -Django's built-in admin interface provides the way to map a "site" (hostname or domain) to the root of a wagtail tree. Access this by going to "/django-admin/" and then "Home › Wagtailcore › Sites." To try out a development site, add a single site with the hostname ``localhost`` at port ``8000`` and map it to one of the pieces of content you have created.. -Model Design -~~~~~~~~~~~~ +Model Design with Wagtail +~~~~~~~~~~~~~~~~~~~~~~~~~ Wagtail manages content internally as a tree of pages. Each node in the tree is an instance of a Django model which subclasses the Wagtail ``Page`` class. You define the structure and interrelationships of your Wagtail site by coding these models and then publishing pages which use the models through the Wagtail admin interface. @@ -20,55 +17,60 @@ Wagtail provides some properties in the Page class which are common to most webp Public Properties Suitable for Inclusion in Templates ````````````````````````````````````````````````````` -``title`` (required) - Human-readable title for the content -``slug`` (required) - Machine-readable URL component for this piece of content. The name of the page as it will appear in URLs e.g ``http://domain.com/blog/[my-slug]/`` + ``title`` (string, required) + Human-readable title for the content -``seo_title`` - Alternate SEO-crafted title which overrides the normal title for use in the ```` of a page + ``slug`` (string, required) + Machine-readable URL component for this piece of content. The name of the page as it will appear in URLs e.g ``http://domain.com/blog/[my-slug]/`` -``search_description`` - A SEO-crafted description of the content, used in both internal search indexing and for the meta description read by search engines + ``seo_title`` (string) + Alternate SEO-crafted title which overrides the normal title for use in the ```` of a page -Private Properties Meant for Use in the Wagtail Admin -````````````````````````````````````````````````````` -``show_in_menus`` - Boolean (checkbox) - Whether a link to this page will appear in automatically generated menus")) + ``search_description`` (string) + A SEO-crafted description of the content, used in both internal search indexing and for the meta description read by search engines -``live`` - Boolean (content status selectors) - whether the page is in a published, public-visible state +Semi-Private Properties Intended for Use in the Wagtail Admin +````````````````````````````````````````````````````````````` -``has_unpublished_changes`` - Boolean (content status selectors) - whether the page is in a draft state + ``show_in_menus`` (boolean) + Whether a link to this page will appear in automatically generated menus")) -``owner`` - User who owns the page + ``live`` (boolean) + Whether the page is in a published, public-visible state + + ``has_unpublished_changes`` (boolean) + Whether the page is in a draft state + + ``owner`` (User) + Model relation pointing to the user who owns the page. Uses the user model set in ``settings.AUTH_USER_MODEL``. + + ``indexed_fields`` (dict) + Describes the properties which should be indexed by search and how they should be weighted for maximum accuracy. See the Search section for usage. Internal Properties Which Describe The Model Instance ````````````````````````````````````````````````````` -``content_type`` - ??? Used to keep track of class names -``url_path`` - The full URL path, including the slugs of all parents going back to the site root. Whenever a slug is changed in the tree, all of the node's descendants are updated with the new path. + ``content_type`` (ContentType) + A relation to an internal content type model. + + ``url_path`` (string) + The full URL path, including the slugs of all parents going back to the site root. Whenever a slug is changed in the tree, all of the node's descendants are updated with the new path. Use the ``pageurl`` template tag for outputting the URL of a page-subclassed object. Introduction to Trees --------------------- -If you're unfamiliar with trees as an abstract data type, you might want to review the concepts involved: -http://en.wikipedia.org/wiki/Tree_(data_structure) +If you're unfamiliar with trees as an abstract data type, you might want to `review the concepts involved. `_ As a web developer, though, you probably already have a good understanding of trees as filesystem directories or paths. Wagtail pages can create the same structure, as each page in the tree has its own URL path, like so:: - / - people/ - nien-nunb/ - laura-roslin/ - events/ - captain-picard-day/ - winter-wrap-up/ + / + people/ + nien-nunb/ + laura-roslin/ + events/ + captain-picard-day/ + winter-wrap-up/ The Wagtail admin interface uses the tree to organize content for editing, letting you navigate up and down levels in the tree through its Explorer menu. This method of organization is a good place to start in thinking about your own Wagtail models. @@ -76,7 +78,7 @@ The Wagtail admin interface uses the tree to organize content for editing, letti Nodes and Leaves ---------------- -It might be handy to think of the Page-derived models you want to create as being one of two node types: parents and leaves. +It might be handy to think of the ``Page``-derived models you want to create as being one of two node types: parents and leaves. Parents ``````` @@ -84,17 +86,17 @@ Parent nodes on the Wagtail tree probably want to organize and display a browsab A Parent node could provide its own function returning its descendant objects. :: - class EventPageIndex(Page): - ... - def events(self): - # Get list of event pages that are descendants of this page - events = EventPage.objects.filter( - live=True, - path__startswith=self.path - ) - return events + class EventPageIndex(Page): + ... + def events(self): + # Get list of event pages that are descendants of this page + events = EventPage.objects.filter( + live=True, + path__startswith=self.path + ) + return events -This example makes sure to limit the returned objects to pieces of content which make sense, specifically ones which have been published through Wagtail's admin interface (live=True) and are descendants of this node. Wagtail will allow the "illogical" placement of child nodes under a parent, so it's necessary for a parent model to index only those children which make sense. +This example makes sure to limit the returned objects to pieces of content which make sense, specifically ones which have been published through Wagtail's admin interface (``live=True``) and are descendants of this node. Wagtail will allow the "illogical" placement of child nodes under a parent, so it's necessary for a parent model to index only those children which make sense. Leaves `````` @@ -102,65 +104,147 @@ Leaves are the pieces of content itself, a page which is consumable, and might j It might be helpful for a leaf to provide a way to back up along the tree to a parent, such as in the case of breadcrumbs navigation. The tree might also be deep enough that a leaf's parent won't be included in general site navigation. -The model for the leaf could provide a function that traverses the tree in the opposite direction and returns an appropriate ancestor.:: +The model for the leaf could provide a function that traverses the tree in the opposite direction and returns an appropriate ancestor:: - class BlogPage(Page): - ... - def blog_index(self): - # Find blog index in ancestors - for ancestor in reversed(self.get_ancestors()): - if isinstance(ancestor.specific, BlogIndexPage): - return ancestor + class BlogPage(Page): + ... + def blog_index(self): + # Find blog index in ancestors + for ancestor in reversed(self.get_ancestors()): + if isinstance(ancestor.specific, BlogIndexPage): + return ancestor - # No ancestors are blog indexes, just return first blog index in database - return BlogIndexPage.objects.first() + # No ancestors are blog indexes, just return first blog index in database + return BlogIndexPage.objects.first() Since Wagtail doesn't limit what Page-derived classes can be assigned as parents and children, the reverse tree traversal needs to accommodate cases which might not be expected, such as the lack of a "logical" parent to a leaf. Other Relationships ``````````````````` -Your Page-derived models might have other interrelationships which extend the basic Wagtail tree or depart from it entirely. You could provide functions to navigate between siblings, such as a "Next Post" link on a blog page(post->post->post). It might make sense for subtrees to interrelate, such as in a discussion forum (forum->post->replies) Skipping across the hierarchy might make sense, too, as all objects of a certain model class might interrelate regardless of their ancestors (events = EventPage.objects.all). Since there's no restriction on the combination of model classes that can be used at any point in the tree, and it's largely up to the models to define their interrelations, the possibilities are really endless. +Your ``Page``-derived models might have other interrelationships which extend the basic Wagtail tree or depart from it entirely. You could provide functions to navigate between siblings, such as a "Next Post" link on a blog page (``post->post->post``). It might make sense for subtrees to interrelate, such as in a discussion forum (``forum->post->replies``) Skipping across the hierarchy might make sense, too, as all objects of a certain model class might interrelate regardless of their ancestors (``events = EventPage.objects.all``). Since there's no restriction on the combination of model classes that can be used at any point in the tree, and it's largely up to the models to define their interrelations, the possibilities are really endless. -Advanced --------- +Model Recipes +------------- - custom serve methods - iCal - JSON +Overriding the Serve() Method +````````````````````````````` - custom route methods +Wagtail defaults to serving ``Page``-derived models by passing ``self`` to a Django HTML template matching the model's name, but suppose you wanted to serve something other than HTML? You can override the ``serve()`` method provided by the ``Page`` class and handle the Django request and response more directly. - ParentalKey for storing groups of stuff to a Page-thing +Consider this example from the Wagtail demo site's ``models.py``, which serves an ``EventPage`` object as an iCal file if the ``format`` variable is set in the request:: - ClusterTaggableManager for tagging + class EventPage(Page): + ... + def serve(self, request): + if "format" in request.GET: + if request.GET['format'] == 'ical': + # Export to ical format + response = HttpResponse( + export_event(self, 'ical'), + content_type='text/calendar', + ) + response['Content-Disposition'] = 'attachment; filename=' + self.slug + '.ics' + return response + else: + # Unrecognised format error + message = 'Could not export event\n\nUnrecognised format: ' + request.GET['format'] + return HttpResponse(message, content_type='text/plain') + else: + # Display event page as usual + return super(EventPage, self).serve(request) - Orderable - Provides an abstract group of properties for ordering a collection of stuff +``serve()`` takes a Django request object and returns a Django response object. Wagtail returns a ``TemplateResponse`` object with the template and context which it generates, which allows middleware to function as intended, so keep in mind that a simpler response object like a ``HttpResponse`` will not receive these benefits. - Using or subclassing the site model? +With this strategy, you could use Django or Python utilities to render your model in JSON or XML or any other format you'd like. + +Tagging +``````` +Wagtail provides tagging capability through the combination of two django modules, ``taggit`` and ``modelcluster``. ``taggit`` provides a model for tags which is extended by ``modelcluster``, which in turn provides some magical database abstraction which makes drafts and revisions possible in Wagtail. It's a tricky recipe, but the net effect is a many-to-many relationship between your model and a tag class reserved for your model. + +Using an example from the Wagtail demo site, here's what the tag model and the relationship field looks like in ``models.py``:: + + from modelcluster.fields import ParentalKey + from modelcluster.tags import ClusterTaggableManager + from taggit.models import Tag, TaggedItemBase + ... + class BlogPageTag(TaggedItemBase): + content_object = ParentalKey('demo.BlogPage', related_name='tagged_items') + ... + class BlogPage(Page): + ... + tags = ClusterTaggableManager(through=BlogPageTag, blank=True) + + BlogPage.promote_panels = [ + ... + FieldPanel('tags'), + ] + +Wagtail's admin provides a nice interface for inputting tags into your content, with typeahead tag completion and friendly tag icons. + +Now that we have the many-to-many tag relationship in place, we can fit in a way to render both sides of the relation. Here's more of the Wagtail demo site ``models.py``, where the index model for ``BlogPage`` is extended with logic for filtering the index by tag:: + + class BlogIndexPage(Page): + ... + def serve(self, request): + # Get blogs + blogs = self.blogs + + # Filter by tag + tag = request.GET.get('tag') + if tag: + blogs = blogs.filter(tags__name=tag) + + return render(request, self.template, { + 'self': self, + 'blogs': blogs, + }) + +Here, ``blogs.filter(tags__name=tag)`` invokes a reverse Django queryset filter on the ``BlogPageTag`` model to optionally limit the ``BlogPage`` objects sent to the template for rendering. Now, lets render both sides of the relation by showing the tags associated with an object and a way of showing all of the objects associated with each tag. This could be added to the ``blog_page.html`` template:: + + {% for tag in self.tags.all %} + {{ tag }} + {% endfor %} + +Iterating through ``self.tags.all`` will display each tag associated with ``self``, while the link(s) back to the index make use of the filter option added to the ``BlogIndexPage`` model. A Django query could also use the ``tagged_items`` related name field to get ``BlogPage`` objects associated with a tag. + +This is just one possible way of creating a taxonomy for Wagtail objects. With all of the components for a taxonomy available through Wagtail, you should be able to fulfill even the most exotic taxonomic schemes. -Wagtail Admin -~~~~~~~~~~~~~ + + custom route methods + + ParentalKey for storing groups of stuff to a Page-thing + + + Orderable + Provides an abstract group of properties for ordering a collection of stuff + + Using or subclassing the site model? + + Extending indexed_fields and making models search-friendly + + +Wagtail Admin API +~~~~~~~~~~~~~~~~~ Fields & Edit Handlers ---------------------- - RichTextField + RichTextField - Image + Image - FieldPanel + FieldPanel - MultiFieldPanel + MultiFieldPanel - InlinePanel + InlinePanel - PageChooserPanel + PageChooserPanel - ImageChooserPanel + ImageChooserPanel - DocumentChooserPanel + DocumentChooserPanel Snippets -------- @@ -174,65 +258,81 @@ Templates Location -------- - Wagtail looks for templates matching your models in... + Wagtail looks for templates matching your models in... Self ---- - Without a custom rendering function, a + Without a custom rendering function, a ... -Tags Provided by Wagtail ------------------------- - pageurl - Loaded into a template with - {% load pageurl %} - Used like - - Given a Page-derived class, outputs a page's URL as relative (/foo/bar/) if it's within the same site as the current page, or absolute (http://example.com/foo/bar/) if not. - slugurl - Loaded into a template with - {% load slugurl %} - Used like - - Returns the URL for the page that has the given slug. Like pageurl, will try to provide a relative link if possible, but will default to an absolute link if on a different site. - wagtailuserbar - Loaded into a template with - {% load wagtailuserbar %} - Used like - {% wagtailuserbar %} - This tag provides a Wagtail icon and flyout menu on the top-right of a page for a logged-in user with editing capabilities, with the option of editing the current Page-derived object or adding a new sibling object. - image - Loaded with - {% load image_tags %} - Used with - {% image self.photo max-320x200 %} - {% image self.photo max-320x200 as img %} - This template tag provides a way to process an image with a method and dimensions +Template Tags +------------- - 'max': 'resize_to_max', - 'min': 'resize_to_min', - 'width': 'resize_to_width', - 'height': 'resize_to_height', - 'fill': 'resize_to_fill', + **pageurl** + + Takes a ``Page``-derived object and returns its URL as relative (``/foo/bar/``) if it's within the same site as the current page, or absolute (``http://example.com/foo/bar/``) if not. :: + + {% load pageurl %} + ... + + + **slugurl** + + Takes a ``slug`` string and returns the URL for the ``Page``-derived object with that slug. Like ``pageurl``, will try to provide a relative link if possible, but will default to an absolute link if on a different site. :: + + {% load slugurl %} + ... + + + **wagtailuserbar** + + This tag provides a Wagtail icon and flyout menu on the top-right of a page for a logged-in user with editing capabilities, with the option of editing the current Page-derived object or adding a new sibling object. :: + + {% load wagtailuserbar %} + ... + {% wagtailuserbar %} + + **image** + + This template tag provides a way to process an image with a method and dimensions. :: + + {% load image_tags %} + ... + {% image self.photo max-320x200 %} + or + {% image self.photo max-320x200 as img %} + + 'max': 'resize_to_max', + 'min': 'resize_to_min', + 'width': 'resize_to_width', + 'height': 'resize_to_height', + 'fill': 'resize_to_fill', -Filters Provided by Wagtail ---------------------------- - rich_text - Loaded into template with - {% load rich_text %} - Used with - {{ body|richtext }} - This filter is required for use with any RichTextField, because it will expand internal shorthand references to embeds and links made in the Wagtail editor into fully-baked HTML ready for display. +Template Filters +---------------- + + **rich_text** + + This filter is required for use with any ``RichTextField``. It will expand internal shorthand references to embeds and links made in the Wagtail editor into fully-baked HTML ready for display. **Note that the template tag loaded differs from the name of the filter.** :: + + {% load rich_text %} + ... + {{ body|richtext }} + +Site +~~~~ + +Django's built-in admin interface provides the way to map a "site" (hostname or domain) to the root of a wagtail tree. Access this by going to ``/django-admin/`` and then "Home › Wagtailcore › Sites." To try out a development site, add a single site with the hostname ``localhost`` at port ``8000`` and map it to one of the pieces of content you have created. Advanced Wagtail ~~~~~~~~~~~~~~~~ - replacing image processing backend + replacing image processing backend - custom image processing methods? + custom image processing methods? - wagtail user bar custom CSS option? + wagtail user bar custom CSS option? From e6df0ef01fbabeba5eac74f6e5d22396e1f475b6 Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Thu, 8 May 2014 21:01:47 -0400 Subject: [PATCH 20/57] stuff --- docs/building_your_site.rst | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/building_your_site.rst b/docs/building_your_site.rst index 9dd98ecfc..95215cbdf 100644 --- a/docs/building_your_site.rst +++ b/docs/building_your_site.rst @@ -221,7 +221,6 @@ This is just one possible way of creating a taxonomy for Wagtail objects. With a Using or subclassing the site model? - Extending indexed_fields and making models search-friendly Wagtail Admin API @@ -319,6 +318,19 @@ Template Filters ... {{ body|richtext }} +Search +~~~~~~ + + + Extending indexed_fields and making models search-friendly + + + + + + + + Site ~~~~ From cf99f5f9f03b4c1204e6f893771a11bc772f8c01 Mon Sep 17 00:00:00 2001 From: tulpar008 Date: Fri, 9 May 2014 11:45:52 +0800 Subject: [PATCH 21/57] translate :34 --- wagtail/wagtailadmin/locale/zh/LC_MESSAGES/django.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wagtail/wagtailadmin/locale/zh/LC_MESSAGES/django.po b/wagtail/wagtailadmin/locale/zh/LC_MESSAGES/django.po index 80a75d43f..954cfc62b 100644 --- a/wagtail/wagtailadmin/locale/zh/LC_MESSAGES/django.po +++ b/wagtail/wagtailadmin/locale/zh/LC_MESSAGES/django.po @@ -31,7 +31,7 @@ msgstr "搜索词" #: .\forms.py:42 msgid "Enter your username" -msgstr "" +msgstr "请输入用户名" #: .\forms.py:45 msgid "Enter password" From abdab87ec388b02478f78fc8822cf7b7f4f39cb9 Mon Sep 17 00:00:00 2001 From: wwj718 Date: Fri, 9 May 2014 13:05:10 +0800 Subject: [PATCH 22/57] Translated wagtailadmin into Chinese language. --- wagtail/wagtailadmin/locale/zh/LC_MESSAGES/django.po | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/wagtail/wagtailadmin/locale/zh/LC_MESSAGES/django.po b/wagtail/wagtailadmin/locale/zh/LC_MESSAGES/django.po index 80a75d43f..c43755acc 100644 --- a/wagtail/wagtailadmin/locale/zh/LC_MESSAGES/django.po +++ b/wagtail/wagtailadmin/locale/zh/LC_MESSAGES/django.po @@ -31,11 +31,11 @@ msgstr "搜索词" #: .\forms.py:42 msgid "Enter your username" -msgstr "" +msgstr "请输入用户名" #: .\forms.py:45 msgid "Enter password" -msgstr "" +msgstr "请输入密码" #: .\forms.py:50 msgid "Enter your email address to reset your password" @@ -89,7 +89,7 @@ msgstr "登录Wagtail" #: .\templates\wagtailadmin\login.html:42 msgid "Forgotten it?" -msgstr "忘记了?" +msgstr "忘记密码?" #: .\templates\wagtailadmin\account\account.html:4 msgid "Account" @@ -104,7 +104,7 @@ msgid "" "Your avatar image is provided by Gravatar and is connected to your email " "address. With a Gravatar account you can set an avatar for any number of " "other email addresses you use." -msgstr "您的头像图片是由Gravatar提供的,并且关联了您的电子邮件地址。一个Gravatar账号可以设置多个电子邮件地址的头像图片。" +msgstr "您的头像图片是由Gravatar提供的,并且关联了您的电子邮箱。一个Gravatar账号可以设置多个电子邮箱的头像图片。" #: .\templates\wagtailadmin\account\account.html:23 #: .\templates\wagtailadmin\account\change_password.html:4 @@ -113,7 +113,7 @@ msgstr "修改密码" #: .\templates\wagtailadmin\account\account.html:27 msgid "Change the password you use to log in." -msgstr "修改您用于登录的密码。" +msgstr "修改登录密码。" #: .\templates\wagtailadmin\account\change_password.html:16 msgid "Change Password" From cb3c41222c3119e38aafeb4fac18865a3ad1e3fe Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Sat, 10 May 2014 01:23:58 -0400 Subject: [PATCH 23/57] omg search --- docs/building_your_site.rst | 6 -- docs/wagtail_search.rst | 116 +++++++++++++++++++++++++++++++++++- 2 files changed, 113 insertions(+), 9 deletions(-) diff --git a/docs/building_your_site.rst b/docs/building_your_site.rst index 95215cbdf..b52d797a1 100644 --- a/docs/building_your_site.rst +++ b/docs/building_your_site.rst @@ -318,12 +318,6 @@ Template Filters ... {{ body|richtext }} -Search -~~~~~~ - - - Extending indexed_fields and making models search-friendly - diff --git a/docs/wagtail_search.rst b/docs/wagtail_search.rst index 1bef60724..4c6ce62f2 100644 --- a/docs/wagtail_search.rst +++ b/docs/wagtail_search.rst @@ -1,7 +1,113 @@ Search ====== -Wagtail can degrade to a database-backed text search, but we strongly recommend `Elasticsearch`_. If you prefer not to run an Elasticsearch server in development or production, there are many hosted services available, including `Searchly`_, who offer a free account suitable for testing and development. To use Searchly: +Wagtail provides a very comprehensive, extensible, and flexible search interface. In addition, it provides ways to promote search results through "Editor's Picks." Wagtail also collects simple statistics on queries made through the search interface. + +Default Page Search +------------------- + +Wagtail provides a default frontend search interface which indexes the ``title`` field common to all ``Page``-derived models. Lets take a look at all the components of the search interface. + +The most basic search functionality just needs a search box which submits a request. Since this will be reused throughout the site, lets put it in ``mysite/includes/search_box.html`` and then use ``{% include ... %}`` to weave it into templates:: + +
+ + +
+ +The form is submitted to the url of the ``wagtailsearch_search`` view, with the search terms variable ``q``. The view will use its own (very) basic search results template. + +Lets use our own template for the results, though. First, in your project's ``settings.py``, define a path to your template:: + + WAGTAILSEARCH_RESULTS_TEMPLATE = 'mysite/search_results.html' + +Next, lets look at the template itself:: + + {% extends "mysite/base.html" %} + {% load pageurl %} + + {% block title %}Search{% if search_results %} Results{% endif %}{% endblock %} + + {% block search_box %} + {% include "mysite/includes/search_box.html" with query_string=query_string only %} + {% endblock %} + + {% block content %} +

Search Results{% if request.GET.q %} for {{ request.GET.q }}{% endif %}

+
+ {% endblock %} + +The search view returns a context with a few useful variables. + + ``query_string`` + The terms (string) used to make the search. + + ``search_results`` + A collection of Page objects matching the query. + + ``is_ajax`` + Boolean. This returns Django's ``request.is_ajax()``. + + ``query`` + The Query object matching the terms. The query model provides several class methods for viewing the statistics of all queries, but exposes only one property for single queries, ``query.hits``, which tracks the number of time the search string has been used. + + + + +Default Page Search with AJAX +----------------------------- + + + +Editor's Picks +-------------- + + + + +Indexing Custom Fields & Custom Search Views +-------------------------------------------- + + + + + + + +Strategies for Total Search Coverage +------------------------------------ + +Want every field searchable? Every custom model and each of their custom fields? Here's how... + + + +Search Backends +--------------- + +Wagtail can degrade to a database-backed text search, but we strongly recommend `Elasticsearch`_. + +.. _Elasticsearch: http://www.elasticsearch.org/ + + +Default DB Backend +`````````````````` +The default DB search backend effectively acts as a ``__icontains`` filter on the ``indexed_fields`` of your models. + + +Elasticsearch Backend +````````````````````` +If you prefer not to run an Elasticsearch server in development or production, there are many hosted services available, including `Searchly`_, who offer a free account suitable for testing and development. To use Searchly: - Sign up for an account at `dashboard.searchly.com/users/sign\_up`_ - Use your Searchly dashboard to create a new index, e.g. 'wagtaildemo' @@ -10,6 +116,10 @@ Wagtail can degrade to a database-backed text search, but we strongly recommend your local settings - Run ``./manage.py update_index`` -.. _Elasticsearch: http://www.elasticsearch.org/ .. _Searchly: http://www.searchly.com/ -.. _dashboard.searchly.com/users/sign\_up: https://dashboard.searchly.com/users/sign_up \ No newline at end of file +.. _dashboard.searchly.com/users/sign\_up: https://dashboard.searchly.com/users/sign_up + + +Rolling Your Own +```````````````` + From 876283debfbc4c9f5e029b157e6c344ce0e1e076 Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Sat, 10 May 2014 01:35:52 -0400 Subject: [PATCH 24/57] omg search --- docs/wagtail_search.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/wagtail_search.rst b/docs/wagtail_search.rst index 4c6ce62f2..c43a53737 100644 --- a/docs/wagtail_search.rst +++ b/docs/wagtail_search.rst @@ -54,13 +54,13 @@ The search view returns a context with a few useful variables. The terms (string) used to make the search. ``search_results`` - A collection of Page objects matching the query. + A collection of Page objects matching the query. The ``specific`` property of ``Page`` will give the most-specific subclassed model object for the Wagtail page. For instance, if an ``Event`` model derived from the basic Wagtail ``Page`` were included in the search results, you could use ``specific`` to access the custom properties of the ``Event`` model (``result.specific.date_of_event``). ``is_ajax`` Boolean. This returns Django's ``request.is_ajax()``. ``query`` - The Query object matching the terms. The query model provides several class methods for viewing the statistics of all queries, but exposes only one property for single queries, ``query.hits``, which tracks the number of time the search string has been used. + A Wagtail Query object matching the terms. The query model provides several class methods for viewing the statistics of all queries, but exposes only one property for single objects, ``query.hits``, which tracks the number of time the search string has been used over the lifetime of the site. From 206a3e3732bed4e11f53b4abac66f55c6c135c03 Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Sat, 10 May 2014 16:49:05 -0400 Subject: [PATCH 25/57] Async search docs done --- docs/building_your_site.rst | 44 ++++++++++++---- docs/conf.py | 2 +- docs/wagtail_search.rst | 100 +++++++++++++++++++++++++++++++++--- 3 files changed, 128 insertions(+), 18 deletions(-) diff --git a/docs/building_your_site.rst b/docs/building_your_site.rst index b52d797a1..4c62d8cab 100644 --- a/docs/building_your_site.rst +++ b/docs/building_your_site.rst @@ -84,7 +84,9 @@ Parents ``````` Parent nodes on the Wagtail tree probably want to organize and display a browsable index of their descendents. A blog, for instance, needs a way to show a list of individual posts. -A Parent node could provide its own function returning its descendant objects. :: +A Parent node could provide its own function returning its descendant objects. + +.. code-block:: python class EventPageIndex(Page): ... @@ -104,7 +106,9 @@ Leaves are the pieces of content itself, a page which is consumable, and might j It might be helpful for a leaf to provide a way to back up along the tree to a parent, such as in the case of breadcrumbs navigation. The tree might also be deep enough that a leaf's parent won't be included in general site navigation. -The model for the leaf could provide a function that traverses the tree in the opposite direction and returns an appropriate ancestor:: +The model for the leaf could provide a function that traverses the tree in the opposite direction and returns an appropriate ancestor: + +.. code-block:: python class BlogPage(Page): ... @@ -131,7 +135,9 @@ Overriding the Serve() Method Wagtail defaults to serving ``Page``-derived models by passing ``self`` to a Django HTML template matching the model's name, but suppose you wanted to serve something other than HTML? You can override the ``serve()`` method provided by the ``Page`` class and handle the Django request and response more directly. -Consider this example from the Wagtail demo site's ``models.py``, which serves an ``EventPage`` object as an iCal file if the ``format`` variable is set in the request:: +Consider this example from the Wagtail demo site's ``models.py``, which serves an ``EventPage`` object as an iCal file if the ``format`` variable is set in the request: + +.. code-block:: python class EventPage(Page): ... @@ -161,7 +167,9 @@ Tagging ``````` Wagtail provides tagging capability through the combination of two django modules, ``taggit`` and ``modelcluster``. ``taggit`` provides a model for tags which is extended by ``modelcluster``, which in turn provides some magical database abstraction which makes drafts and revisions possible in Wagtail. It's a tricky recipe, but the net effect is a many-to-many relationship between your model and a tag class reserved for your model. -Using an example from the Wagtail demo site, here's what the tag model and the relationship field looks like in ``models.py``:: +Using an example from the Wagtail demo site, here's what the tag model and the relationship field looks like in ``models.py``: + +.. code-block:: python from modelcluster.fields import ParentalKey from modelcluster.tags import ClusterTaggableManager @@ -181,7 +189,9 @@ Using an example from the Wagtail demo site, here's what the tag model and the r Wagtail's admin provides a nice interface for inputting tags into your content, with typeahead tag completion and friendly tag icons. -Now that we have the many-to-many tag relationship in place, we can fit in a way to render both sides of the relation. Here's more of the Wagtail demo site ``models.py``, where the index model for ``BlogPage`` is extended with logic for filtering the index by tag:: +Now that we have the many-to-many tag relationship in place, we can fit in a way to render both sides of the relation. Here's more of the Wagtail demo site ``models.py``, where the index model for ``BlogPage`` is extended with logic for filtering the index by tag: + +.. code-block:: python class BlogIndexPage(Page): ... @@ -199,7 +209,9 @@ Now that we have the many-to-many tag relationship in place, we can fit in a way 'blogs': blogs, }) -Here, ``blogs.filter(tags__name=tag)`` invokes a reverse Django queryset filter on the ``BlogPageTag`` model to optionally limit the ``BlogPage`` objects sent to the template for rendering. Now, lets render both sides of the relation by showing the tags associated with an object and a way of showing all of the objects associated with each tag. This could be added to the ``blog_page.html`` template:: +Here, ``blogs.filter(tags__name=tag)`` invokes a reverse Django queryset filter on the ``BlogPageTag`` model to optionally limit the ``BlogPage`` objects sent to the template for rendering. Now, lets render both sides of the relation by showing the tags associated with an object and a way of showing all of the objects associated with each tag. This could be added to the ``blog_page.html`` template: + +.. code-block:: django {% for tag in self.tags.all %} {{ tag }} @@ -268,7 +280,9 @@ Template Tags **pageurl** - Takes a ``Page``-derived object and returns its URL as relative (``/foo/bar/``) if it's within the same site as the current page, or absolute (``http://example.com/foo/bar/``) if not. :: + Takes a ``Page``-derived object and returns its URL as relative (``/foo/bar/``) if it's within the same site as the current page, or absolute (``http://example.com/foo/bar/``) if not. + + .. code-block:: django {% load pageurl %} ... @@ -276,7 +290,9 @@ Template Tags **slugurl** - Takes a ``slug`` string and returns the URL for the ``Page``-derived object with that slug. Like ``pageurl``, will try to provide a relative link if possible, but will default to an absolute link if on a different site. :: + Takes a ``slug`` string and returns the URL for the ``Page``-derived object with that slug. Like ``pageurl``, will try to provide a relative link if possible, but will default to an absolute link if on a different site. + + .. code-block:: django {% load slugurl %} ... @@ -284,7 +300,9 @@ Template Tags **wagtailuserbar** - This tag provides a Wagtail icon and flyout menu on the top-right of a page for a logged-in user with editing capabilities, with the option of editing the current Page-derived object or adding a new sibling object. :: + This tag provides a Wagtail icon and flyout menu on the top-right of a page for a logged-in user with editing capabilities, with the option of editing the current Page-derived object or adding a new sibling object. + + .. code-block:: django {% load wagtailuserbar %} ... @@ -292,7 +310,9 @@ Template Tags **image** - This template tag provides a way to process an image with a method and dimensions. :: + This template tag provides a way to process an image with a method and dimensions. + + .. code-block:: django {% load image_tags %} ... @@ -312,7 +332,9 @@ Template Filters **rich_text** - This filter is required for use with any ``RichTextField``. It will expand internal shorthand references to embeds and links made in the Wagtail editor into fully-baked HTML ready for display. **Note that the template tag loaded differs from the name of the filter.** :: + This filter is required for use with any ``RichTextField``. It will expand internal shorthand references to embeds and links made in the Wagtail editor into fully-baked HTML ready for display. **Note that the template tag loaded differs from the name of the filter.** + + .. code-block:: django {% load rich_text %} ... diff --git a/docs/conf.py b/docs/conf.py index 11517ada2..4112e3753 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -93,7 +93,7 @@ exclude_patterns = ['_build'] #show_authors = False # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +#pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] diff --git a/docs/wagtail_search.rst b/docs/wagtail_search.rst index c43a53737..c3ebd236c 100644 --- a/docs/wagtail_search.rst +++ b/docs/wagtail_search.rst @@ -8,7 +8,9 @@ Default Page Search Wagtail provides a default frontend search interface which indexes the ``title`` field common to all ``Page``-derived models. Lets take a look at all the components of the search interface. -The most basic search functionality just needs a search box which submits a request. Since this will be reused throughout the site, lets put it in ``mysite/includes/search_box.html`` and then use ``{% include ... %}`` to weave it into templates:: +The most basic search functionality just needs a search box which submits a request. Since this will be reused throughout the site, lets put it in ``mysite/includes/search_box.html`` and then use ``{% include ... %}`` to weave it into templates: + +.. code-block:: django
@@ -17,11 +19,15 @@ The most basic search functionality just needs a search box which submits a requ The form is submitted to the url of the ``wagtailsearch_search`` view, with the search terms variable ``q``. The view will use its own (very) basic search results template. -Lets use our own template for the results, though. First, in your project's ``settings.py``, define a path to your template:: +Lets use our own template for the results, though. First, in your project's ``settings.py``, define a path to your template: + +.. code-block:: python WAGTAILSEARCH_RESULTS_TEMPLATE = 'mysite/search_results.html' -Next, lets look at the template itself:: +Next, lets look at the template itself: + +.. code-block:: django {% extends "mysite/base.html" %} {% load pageurl %} @@ -48,7 +54,7 @@ Next, lets look at the template itself:: {% endblock %} -The search view returns a context with a few useful variables. +The search view provides a context with a few useful variables. ``query_string`` The terms (string) used to make the search. @@ -62,13 +68,95 @@ The search view returns a context with a few useful variables. ``query`` A Wagtail Query object matching the terms. The query model provides several class methods for viewing the statistics of all queries, but exposes only one property for single objects, ``query.hits``, which tracks the number of time the search string has been used over the lifetime of the site. +Asyncronous Search with JSON and AJAX +------------------------------------- +Wagtail's provides JSON search results when queries are made to the ``wagtailsearch_suggest`` view. To take advantage of it, we need a way to make that URL available to a static script. Instead of hard-coding it, lets set a global variable in our ``base.html``: +.. code-block:: django -Default Page Search with AJAX ------------------------------ + +Lets also add a simple interface for the search with an ```` element and ``
`` for the results: +.. code-block:: html + +
+

Search

+ +
+
+ +Finally, we'll use JQuery to make the aynchronous requests and handle the interactivity: + +.. code-block:: guess + + $(function() { + + // cache the elements + var searchBox = $('#json-search'), + resultsBox = $('#json-results'); + // when there's something in the input box, make the query + searchBox.on('input', function() { + if( searchBox.val() == ''){ + resultsBox.html(''); + return; + } + // make the request to the Wagtail JSON search view + $.ajax({ + url: wagtailJSONSearchURL + "?q=" + searchBox.val(), + dataType: "json" + }) + .done(function(data) { + console.log(data); + if( data == undefined ){ + resultsBox.html(''); + return; + } + // we're in business! let's format the results + var htmlOutput = ''; + data.forEach(function(element, index, array){ + htmlOutput += '

' + element.title + '

'; + }); + // and display them + resultsBox.html(htmlOutput); + }) + .error(function(data){ + console.log(data); + }); + }); + + }); + +Results are returned as a JSON object with this structure: + +.. code-block:: guess + + { + [ + { + title: "Lumpy Space Princess", + url: "/oh-my-glob/" + }, + { + title: "Lumpy Space", + url: "/no-smooth-posers/" + }, + ... + ] + } + +What if you wanted access to the rest of the results context or didn't feel like using JSON? Wagtail also provides a generalized AJAX interface where you can use your own template to serve results asyncronously. + +The AJAX interface uses the same view as the normal HTML search, ``wagtailsearch_search``, but will serve different results if Django classifies the request as AJAX (``request.is_ajax()``). Another entry in your project settings will let you override the template used to serve this response: + +.. code-block:: python + + WAGTAILSEARCH_RESULTS_TEMPLATE_AJAX = 'mirrorstage/includes/search_listing.html' + +You could provide a template in JSON format with extra properties, such as ``query.hits``, or render an HTML snippet that can go directly into your results ``
``. If you need more flexibility, such as multiple formats/templates based on differing requests, you can set up a custom search view. Editor's Picks -------------- From c4b5f09eace7d56b25404a13c3d87eb148c0a709 Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Sat, 10 May 2014 16:52:19 -0400 Subject: [PATCH 26/57] Async search docs done --- docs/wagtail_search.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/wagtail_search.rst b/docs/wagtail_search.rst index c3ebd236c..7af946ec2 100644 --- a/docs/wagtail_search.rst +++ b/docs/wagtail_search.rst @@ -154,9 +154,9 @@ The AJAX interface uses the same view as the normal HTML search, ``wagtailsearch .. code-block:: python - WAGTAILSEARCH_RESULTS_TEMPLATE_AJAX = 'mirrorstage/includes/search_listing.html' + WAGTAILSEARCH_RESULTS_TEMPLATE_AJAX = 'myapp/includes/search_listing.html' -You could provide a template in JSON format with extra properties, such as ``query.hits``, or render an HTML snippet that can go directly into your results ``
``. If you need more flexibility, such as multiple formats/templates based on differing requests, you can set up a custom search view. +In this template, you'll have access to the same context variablies provided to the HTML template. You could provide a template in JSON format with extra properties, such as ``query.hits``, or render an HTML snippet that can go directly into your results ``
``. If you need more flexibility, such as multiple formats/templates based on differing requests, you can set up a custom search view. Editor's Picks -------------- From 66d29b37df908864375fc2eba6611eee4afbce7e Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Sun, 11 May 2014 20:07:40 -0400 Subject: [PATCH 27/57] done with search docs --- docs/wagtail_search.rst | 57 +++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/docs/wagtail_search.rst b/docs/wagtail_search.rst index 7af946ec2..517617272 100644 --- a/docs/wagtail_search.rst +++ b/docs/wagtail_search.rst @@ -66,7 +66,9 @@ The search view provides a context with a few useful variables. Boolean. This returns Django's ``request.is_ajax()``. ``query`` - A Wagtail Query object matching the terms. The query model provides several class methods for viewing the statistics of all queries, but exposes only one property for single objects, ``query.hits``, which tracks the number of time the search string has been used over the lifetime of the site. + A Wagtail ``Query`` object matching the terms. The ``Query`` model provides several class methods for viewing the statistics of all queries, but exposes only one property for single objects, ``query.hits``, which tracks the number of time the search string has been used over the lifetime of the site. ``Query`` also joins to the Editor's Picks functionality though ``query.editors_picks``. See :ref:`editors-picks`. + + Asyncronous Search with JSON and AJAX ------------------------------------- @@ -156,28 +158,52 @@ The AJAX interface uses the same view as the normal HTML search, ``wagtailsearch WAGTAILSEARCH_RESULTS_TEMPLATE_AJAX = 'myapp/includes/search_listing.html' -In this template, you'll have access to the same context variablies provided to the HTML template. You could provide a template in JSON format with extra properties, such as ``query.hits``, or render an HTML snippet that can go directly into your results ``
``. If you need more flexibility, such as multiple formats/templates based on differing requests, you can set up a custom search view. +In this template, you'll have access to the same context variablies provided to the HTML template. You could provide a template in JSON format with extra properties, such as ``query.hits`` and editor's picks, or render an HTML snippet that can go directly into your results ``
``. If you need more flexibility, such as multiple formats/templates based on differing requests, you can set up a custom search view. + +.. _editors-picks: Editor's Picks -------------- +Editor's Picks are a way of explicitly linking relevant content to search terms, so results pages can contain curated content instead of being at the mercy of the search algorithm. In a template using the search results view, editor's picks can be accessed through the variable ``query.editors_picks``. To include editor's picks in your search results template, use the following properties. +``query.editors_picks.all`` + This gathers all of the editor's picks objects relating to the current query, in order according to their sort order in the Wagtail admin. You can then iterate through them using a ``{% for ... %}`` loop. Each editor's pick object provides these properties: + ``editors_pick.page`` + The page object associated with the pick. Use ``{% pageurl editors_pick.page %}`` to generate a URL or provide other properties of the page object. + + ``editors_pick.description`` + The description entered when choosing the pick, perhaps explaining why the page is relevant to the search terms. + +Putting this all together, a block of your search results template displaying Editor's Picks might look like this: + +.. code-block:: django + + {% with query.editors_picks.all as editors_picks %} + {% if editors_picks %} +
+

Editors picks

+ +
+ {% endif %} + {% endwith %} Indexing Custom Fields & Custom Search Views -------------------------------------------- - - - - - - -Strategies for Total Search Coverage ------------------------------------- - -Want every field searchable? Every custom model and each of their custom fields? Here's how... - +This functionality is still under active development to provide a streamlined interface, but take a look at ``wagtail/wagtail/wagtailsearch/views/frontend.py`` if you are interested in coding custom search views. Search Backends @@ -190,7 +216,7 @@ Wagtail can degrade to a database-backed text search, but we strongly recommend Default DB Backend `````````````````` -The default DB search backend effectively acts as a ``__icontains`` filter on the ``indexed_fields`` of your models. +The default DB search backend uses Django's ``__icontains`` filter. Elasticsearch Backend @@ -207,7 +233,6 @@ If you prefer not to run an Elasticsearch server in development or production, t .. _Searchly: http://www.searchly.com/ .. _dashboard.searchly.com/users/sign\_up: https://dashboard.searchly.com/users/sign_up - Rolling Your Own ```````````````` - +Wagtail search backends implement the interface defined in ``wagtail/wagtail/wagtailsearch/backends/base.py``. At a minimum, the backend's ``search()`` method must return a collection of objects or ``model.objects.none()``. For a fully-featured search backend, examine the Elasticsearch backend code in ``elasticsearch.py``. From e37b6f6a5fa97cf5c24d16ecdc8d036b5cbd0726 Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Mon, 12 May 2014 21:25:26 -0400 Subject: [PATCH 28/57] ugh neck hurt --- docs/building_your_site.rst | 40 ++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/docs/building_your_site.rst b/docs/building_your_site.rst index 4c62d8cab..8912a8158 100644 --- a/docs/building_your_site.rst +++ b/docs/building_your_site.rst @@ -227,10 +227,6 @@ This is just one possible way of creating a taxonomy for Wagtail objects. With a ParentalKey for storing groups of stuff to a Page-thing - - Orderable - Provides an abstract group of properties for ordering a collection of stuff - Using or subclassing the site model? @@ -260,7 +256,41 @@ Fields & Edit Handlers Snippets -------- -Registering and using template tags? +Snippets are pieces of content which do not necessitate a full webpage to render. They could be used for making secondary content, such as headers, footers, and sidebars, editable in the Wagtail admin. Snippets are models which do not inherit the ``Page`` class and are thus not organized into the Wagtail tree, but can still be made editable by assigning panels and identifying the model as a snippet with ``register_snippet()``. + +Here's an example snippet from the Wagtail demo website: + +.. code-block:: python + + class Advert(models.Model): + page = models.ForeignKey( + 'wagtailcore.Page', + related_name='adverts', + null=True, + blank=True + ) + url = models.URLField(null=True, blank=True) + text = models.CharField(max_length=255) + + panels = [ + PageChooserPanel('page'), + FieldPanel('url'), + FieldPanel('text'), + ] + + def __unicode__(self): + return self.text + + register_snippet(Advert) + +The ``Advert`` model uses the basic Django model class and defines three properties: text, url, and page. The editing interface is very close to that provided for ``Page``-derived models, with fields assigned in the panels property. + + + + + + + From a2ed70bd8d862137a955e69a4e8132091c5ba477 Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Tue, 13 May 2014 22:38:44 -0400 Subject: [PATCH 29/57] Snippets and some reorg --- docs/advanced_topics.rst | 9 +++ docs/building_your_site.rst | 144 +++++++----------------------------- docs/index.rst | 3 + docs/panels.rst | 33 +++++++++ docs/snippets.rst | 140 +++++++++++++++++++++++++++++++++++ docs/wagtail_search.rst | 75 +++++++++---------- 6 files changed, 250 insertions(+), 154 deletions(-) create mode 100644 docs/advanced_topics.rst create mode 100644 docs/panels.rst create mode 100644 docs/snippets.rst diff --git a/docs/advanced_topics.rst b/docs/advanced_topics.rst new file mode 100644 index 000000000..ae0e24015 --- /dev/null +++ b/docs/advanced_topics.rst @@ -0,0 +1,9 @@ +Advanced Topics +~~~~~~~~~~~~~~~~ + +replacing image processing backend + +custom image processing tags? + +wagtail user bar custom CSS option? + diff --git a/docs/building_your_site.rst b/docs/building_your_site.rst index 8912a8158..1b4c9dd09 100644 --- a/docs/building_your_site.rst +++ b/docs/building_your_site.rst @@ -1,22 +1,22 @@ Building your site ================== - - -Model Design with Wagtail -~~~~~~~~~~~~~~~~~~~~~~~~~ - Wagtail manages content internally as a tree of pages. Each node in the tree is an instance of a Django model which subclasses the Wagtail ``Page`` class. You define the structure and interrelationships of your Wagtail site by coding these models and then publishing pages which use the models through the Wagtail admin interface. + +The Page Class +~~~~~~~~~~~~~~ + ``Page`` uses Django's model interface, so you can include any field type and field options that Django allows. Wagtail provides some fields and editing handlers that simplify data entry in the Wagtail admin interface, so you may want to keep those in mind when deciding what properties to add to your models in addition to those already provided by ``Page``. + Built-in Properties of the Page Class ------------------------------------- -Wagtail provides some properties in the Page class which are common to most webpages. Since you'll be subclassing ``Page``, you don't have to worry about implementing them. +Wagtail provides some properties in the ``Page`` class which are common to most webpages. Since you'll be subclassing ``Page``, you don't have to worry about implementing them. -Public Properties Suitable for Inclusion in Templates -````````````````````````````````````````````````````` +Public Properties +````````````````` ``title`` (string, required) Human-readable title for the content @@ -30,32 +30,23 @@ Public Properties Suitable for Inclusion in Templates ``search_description`` (string) A SEO-crafted description of the content, used in both internal search indexing and for the meta description read by search engines -Semi-Private Properties Intended for Use in the Wagtail Admin -````````````````````````````````````````````````````````````` +The ``Page`` class actually has alot more to it, but these are probably the only built-in properties you'll need to worry about when creating templates for your models. + + +Anatomy of a Wagtail Model +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +So what does a Wagtail model definition look like? + + - ``show_in_menus`` (boolean) - Whether a link to this page will appear in automatically generated menus")) - ``live`` (boolean) - Whether the page is in a published, public-visible state - ``has_unpublished_changes`` (boolean) - Whether the page is in a draft state - ``owner`` (User) - Model relation pointing to the user who owns the page. Uses the user model set in ``settings.AUTH_USER_MODEL``. - ``indexed_fields`` (dict) - Describes the properties which should be indexed by search and how they should be weighted for maximum accuracy. See the Search section for usage. -Internal Properties Which Describe The Model Instance -````````````````````````````````````````````````````` - ``content_type`` (ContentType) - A relation to an internal content type model. - ``url_path`` (string) - The full URL path, including the slugs of all parents going back to the site root. Whenever a slug is changed in the tree, all of the node's descendants are updated with the new path. Use the ``pageurl`` template tag for outputting the URL of a page-subclassed object. Introduction to Trees --------------------- @@ -78,10 +69,10 @@ The Wagtail admin interface uses the tree to organize content for editing, letti Nodes and Leaves ---------------- -It might be handy to think of the ``Page``-derived models you want to create as being one of two node types: parents and leaves. +It might be handy to think of the ``Page``-derived models you want to create as being one of two node types: parents and leaves. Wagtail isn't prescriptive in this approach, but it's a good place to start if you're not experienced in structuring your own content types. -Parents -``````` +Nodes +````` Parent nodes on the Wagtail tree probably want to organize and display a browsable index of their descendents. A blog, for instance, needs a way to show a list of individual posts. A Parent node could provide its own function returning its descendant objects. @@ -127,11 +118,12 @@ Other Relationships ``````````````````` Your ``Page``-derived models might have other interrelationships which extend the basic Wagtail tree or depart from it entirely. You could provide functions to navigate between siblings, such as a "Next Post" link on a blog page (``post->post->post``). It might make sense for subtrees to interrelate, such as in a discussion forum (``forum->post->replies``) Skipping across the hierarchy might make sense, too, as all objects of a certain model class might interrelate regardless of their ancestors (``events = EventPage.objects.all``). Since there's no restriction on the combination of model classes that can be used at any point in the tree, and it's largely up to the models to define their interrelations, the possibilities are really endless. + Model Recipes -------------- +~~~~~~~~~~~~~ Overriding the Serve() Method -````````````````````````````` +----------------------------- Wagtail defaults to serving ``Page``-derived models by passing ``self`` to a Django HTML template matching the model's name, but suppose you wanted to serve something other than HTML? You can override the ``serve()`` method provided by the ``Page`` class and handle the Django request and response more directly. @@ -164,7 +156,8 @@ Consider this example from the Wagtail demo site's ``models.py``, which serves a With this strategy, you could use Django or Python utilities to render your model in JSON or XML or any other format you'd like. Tagging -``````` +------- + Wagtail provides tagging capability through the combination of two django modules, ``taggit`` and ``modelcluster``. ``taggit`` provides a model for tags which is extended by ``modelcluster``, which in turn provides some magical database abstraction which makes drafts and revisions possible in Wagtail. It's a tricky recipe, but the net effect is a many-to-many relationship between your model and a tag class reserved for your model. Using an example from the Wagtail demo site, here's what the tag model and the relationship field looks like in ``models.py``: @@ -227,69 +220,6 @@ This is just one possible way of creating a taxonomy for Wagtail objects. With a ParentalKey for storing groups of stuff to a Page-thing - Using or subclassing the site model? - - - -Wagtail Admin API -~~~~~~~~~~~~~~~~~ - -Fields & Edit Handlers ----------------------- - - RichTextField - - Image - - FieldPanel - - MultiFieldPanel - - InlinePanel - - PageChooserPanel - - ImageChooserPanel - - DocumentChooserPanel - -Snippets --------- - -Snippets are pieces of content which do not necessitate a full webpage to render. They could be used for making secondary content, such as headers, footers, and sidebars, editable in the Wagtail admin. Snippets are models which do not inherit the ``Page`` class and are thus not organized into the Wagtail tree, but can still be made editable by assigning panels and identifying the model as a snippet with ``register_snippet()``. - -Here's an example snippet from the Wagtail demo website: - -.. code-block:: python - - class Advert(models.Model): - page = models.ForeignKey( - 'wagtailcore.Page', - related_name='adverts', - null=True, - blank=True - ) - url = models.URLField(null=True, blank=True) - text = models.CharField(max_length=255) - - panels = [ - PageChooserPanel('page'), - FieldPanel('url'), - FieldPanel('text'), - ] - - def __unicode__(self): - return self.text - - register_snippet(Advert) - -The ``Advert`` model uses the basic Django model class and defines three properties: text, url, and page. The editing interface is very close to that provided for ``Page``-derived models, with fields assigned in the panels property. - - - - - - @@ -372,32 +302,14 @@ Template Filters - - - - - Site ~~~~ -Django's built-in admin interface provides the way to map a "site" (hostname or domain) to the root of a wagtail tree. Access this by going to ``/django-admin/`` and then "Home › Wagtailcore › Sites." To try out a development site, add a single site with the hostname ``localhost`` at port ``8000`` and map it to one of the pieces of content you have created. - - -Advanced Wagtail -~~~~~~~~~~~~~~~~ - - replacing image processing backend - - custom image processing methods? - - wagtail user bar custom CSS option? - - - - - +Django's built-in admin interface provides the way to map a "site" (hostname or domain) to any node in the wagtail tree, using that node as the site's root. +Access this by going to ``/django-admin/`` and then "Home › Wagtailcore › Sites." To try out a development site, add a single site with the hostname ``localhost`` at port ``8000`` and map it to one of the pieces of content you have created. +Wagtail's developers plan to move the site settings into the Wagtail admin interface. diff --git a/docs/index.rst b/docs/index.rst index dbfe91f33..defbe99cf 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -10,7 +10,10 @@ It supports Django 1.6.2+ on Python 2.6 and 2.7. Django 1.7 and Python 3 support gettingstarted building_your_site + panels + snippets wagtail_search + advanced_topics deploying performance contributing diff --git a/docs/panels.rst b/docs/panels.rst new file mode 100644 index 000000000..7cf6c1056 --- /dev/null +++ b/docs/panels.rst @@ -0,0 +1,33 @@ + +Panels & Edit Handlers +====================== + +RichTextField +~~~~~~~~~~~~~ + +Image +~~~~~ + +FieldPanel +~~~~~~~~~~ + +MultiFieldPanel +~~~~~~~~~~~~~~~ + +InlinePanel +~~~~~~~~~~~ + +PageChooserPanel +~~~~~~~~~~~~~~~~ + +ImageChooserPanel +~~~~~~~~~~~~~~~~~ + +DocumentChooserPanel +~~~~~~~~~~~~~~~~~~~~ + +SnippetChooserPanel +~~~~~~~~~~~~~~~~~~~ + + + diff --git a/docs/snippets.rst b/docs/snippets.rst new file mode 100644 index 000000000..14d62b793 --- /dev/null +++ b/docs/snippets.rst @@ -0,0 +1,140 @@ +Snippets +======== + +Snippets are pieces of content which do not necessitate a full webpage to render. They could be used for making secondary content, such as headers, footers, and sidebars, editable in the Wagtail admin. Snippets are models which do not inherit the ``Page`` class and are thus not organized into the Wagtail tree, but can still be made editable by assigning panels and identifying the model as a snippet with ``register_snippet()``. + +Snippets are not searchable or orderable in the Wagtail admin, so decide carefully if the content type you would want to build into a snippet might be more suited to a page. + +Snippet Models +-------------- + +Here's an example snippet from the Wagtail demo website: + +.. code-block:: python + + from django.db import models + + from wagtail.wagtailadmin.edit_handlers import FieldPanel + from wagtail.wagtailsnippets.models import register_snippet + + ... + + class Advert(models.Model): + url = models.URLField(null=True, blank=True) + text = models.CharField(max_length=255) + + panels = [ + FieldPanel('url'), + FieldPanel('text'), + ] + + def __unicode__(self): + return self.text + + register_snippet(Advert) + +The ``Advert`` model uses the basic Django model class and defines two properties: text and url. The editing interface is very close to that provided for ``Page``-derived models, with fields assigned in the panels property. Snippets do not use multiple tabs of fields, nor do they provide the "save as draft" or "submit for moderation" features. + +``register_snippet(Advert)`` tells Wagtail to treat the model as a snippet. The ``panels`` list defines the fields to show on the snippet editing page. It's also important to provide a string representation of the class through ``def __unicode__(self):`` so that the snippet objects make sense when listed in the Wagtail admin. + +Including Snippets in Template Tags +----------------------------------- + +The simplest way to make your snippets available to templates is with a template tag. This is mostly done with vanilla Django, so perhaps reviewing Django's documentation for `django custom template tags`_ will be more helpful. We'll go over the basics, though, and make note of any considerations to make for Wagtail. + +First, add a new python file to a ``templatetags`` folder within your app. The demo website, for instance uses the path ``wagtaildemo/demo/templatetags/demo_tags.py``. We'll need to load some Django modules and our app's models and ready the ``register`` decorator: + +.. _django custom template tags: https://docs.djangoproject.com/en/dev/howto/custom-template-tags/ + +.. code-block:: python + + from django import template + from demo.models import * + + register = template.Library() + + ... + + # Advert snippets + @register.inclusion_tag('demo/tags/adverts.html', takes_context=True) + def adverts(context): + return { + 'adverts': Advert.objects.all(), + 'request': context['request'], + } + +``@register.inclusion_tag()`` takes two variables: a template and a boolean on whether that template should be passed a request context. It's a good idea to include request contexts in your custom template tags, since some Wagtail-specific template tags like ``pageurl`` need the context to work properly. The template tag function could take arguments and filter the adverts to return a specific model, but for brevity we'll just use ``Advert.objects.all()``. + +Here's what's in the template used by the template tag: + +.. code-block:: django + + {% for advert in adverts %} +

+ + {{ advert.text }} + +

+ {% endfor %} + +Then in your own page templates, you can include your snippet template tag with: + +.. code-block:: django + + {% block content %} + + ... + + {% adverts %} + + {% endblock %} + +Binding Pages to Snippets +------------------------- + +An alternate strategy for including snippets might involve explicitly binding a specific page object to a specific snippet object. Lets add another snippet class to see how that might work: + +.. code-block:: python + + from django.db import models + + from wagtail.wagtailcore.models import Page + from wagtail.wagtailadmin.edit_handlers import PageChooserPanel + from wagtail.wagtailsnippets.models import register_snippet + from wagtail.wagtailsnippets.edit_handlers import SnippetChooserPanel + + from modelcluster.fields import ParentalKey + + ... + + class AdvertPlacement(models.Model): + page = ParentalKey('wagtailcore.Page', related_name='advert_placements') + advert = models.ForeignKey('demo.Advert', related_name='+') + + class Meta: + verbose_name = "Advert Placement" + verbose_name_plural = "Advert Placements" + + panels = [ + PageChooserPanel('page'), + SnippetChooserPanel('advert', Advert), + ] + + def __unicode__(self): + return self.page.title + " -> " + self.advert.text + + register_snippet(AdvertPlacement) + +The class ``AdvertPlacement`` has two properties, ``page`` and ``advert``, which point to other models. Wagtail provides a ``PageChooserPanel`` and ``SnippetChooserPanel`` to let us make painless selection of those properties in the Wagtail admin. Note also the ``Meta`` class, which you can stock with the ``verbose_name`` and ``verbose_name_plural`` properties to override the snippet labels in the Wagtail admin. The text representation of the class has also gotten fancy, using both properties to construct a compound label showing the relationship it forms between a page and an Advert. + +With this snippet in place, we can use the reverse ``related_name`` lookup label ``advert_placements`` to iterate over any placements within our template files. In the template for a ``Page``-derived model, we could include the following: + +.. code-block:: django + + {% if self.advert_placements %} + {% for advert_placement in self.advert_placements.all %} +

{{ advert_placement.advert.text }}

+ {% endfor %} + {% endif %} + + diff --git a/docs/wagtail_search.rst b/docs/wagtail_search.rst index 517617272..fff462349 100644 --- a/docs/wagtail_search.rst +++ b/docs/wagtail_search.rst @@ -68,7 +68,43 @@ The search view provides a context with a few useful variables. ``query`` A Wagtail ``Query`` object matching the terms. The ``Query`` model provides several class methods for viewing the statistics of all queries, but exposes only one property for single objects, ``query.hits``, which tracks the number of time the search string has been used over the lifetime of the site. ``Query`` also joins to the Editor's Picks functionality though ``query.editors_picks``. See :ref:`editors-picks`. +Editor's Picks +-------------- +Editor's Picks are a way of explicitly linking relevant content to search terms, so results pages can contain curated content instead of being at the mercy of the search algorithm. In a template using the search results view, editor's picks can be accessed through the variable ``query.editors_picks``. To include editor's picks in your search results template, use the following properties. + +``query.editors_picks.all`` + This gathers all of the editor's picks objects relating to the current query, in order according to their sort order in the Wagtail admin. You can then iterate through them using a ``{% for ... %}`` loop. Each editor's pick object provides these properties: + + ``editors_pick.page`` + The page object associated with the pick. Use ``{% pageurl editors_pick.page %}`` to generate a URL or provide other properties of the page object. + + ``editors_pick.description`` + The description entered when choosing the pick, perhaps explaining why the page is relevant to the search terms. + +Putting this all together, a block of your search results template displaying Editor's Picks might look like this: + +.. code-block:: django + + {% with query.editors_picks.all as editors_picks %} + {% if editors_picks %} +
+

Editors picks

+ +
+ {% endif %} + {% endwith %} Asyncronous Search with JSON and AJAX ------------------------------------- @@ -81,7 +117,7 @@ Wagtail's provides JSON search results when queries are made to the ``wagtailsea var wagtailJSONSearchURL = "{% url 'wagtailsearch_suggest' %}"; -Lets also add a simple interface for the search with an ```` element and ``
`` for the results: +Lets also add a simple interface for the search with a ```` element to gather search terms and a ``
`` to display the results: .. code-block:: html @@ -162,43 +198,6 @@ In this template, you'll have access to the same context variablies provided to .. _editors-picks: -Editor's Picks --------------- - -Editor's Picks are a way of explicitly linking relevant content to search terms, so results pages can contain curated content instead of being at the mercy of the search algorithm. In a template using the search results view, editor's picks can be accessed through the variable ``query.editors_picks``. To include editor's picks in your search results template, use the following properties. - -``query.editors_picks.all`` - This gathers all of the editor's picks objects relating to the current query, in order according to their sort order in the Wagtail admin. You can then iterate through them using a ``{% for ... %}`` loop. Each editor's pick object provides these properties: - - ``editors_pick.page`` - The page object associated with the pick. Use ``{% pageurl editors_pick.page %}`` to generate a URL or provide other properties of the page object. - - ``editors_pick.description`` - The description entered when choosing the pick, perhaps explaining why the page is relevant to the search terms. - -Putting this all together, a block of your search results template displaying Editor's Picks might look like this: - -.. code-block:: django - - {% with query.editors_picks.all as editors_picks %} - {% if editors_picks %} -
-

Editors picks

- -
- {% endif %} - {% endwith %} Indexing Custom Fields & Custom Search Views -------------------------------------------- From 65b98992699a80390999c11f117068a97222bf2a Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Thu, 15 May 2014 22:41:13 -0400 Subject: [PATCH 30/57] Routes --- docs/building_your_site.rst | 106 ++++++++++++++++++++++++++++++++++-- 1 file changed, 101 insertions(+), 5 deletions(-) diff --git a/docs/building_your_site.rst b/docs/building_your_site.rst index 1b4c9dd09..04c2e2ae5 100644 --- a/docs/building_your_site.rst +++ b/docs/building_your_site.rst @@ -122,7 +122,7 @@ Your ``Page``-derived models might have other interrelationships which extend th Model Recipes ~~~~~~~~~~~~~ -Overriding the Serve() Method +Overriding the serve() Method ----------------------------- Wagtail defaults to serving ``Page``-derived models by passing ``self`` to a Django HTML template matching the model's name, but suppose you wanted to serve something other than HTML? You can override the ``serve()`` method provided by the ``Page`` class and handle the Django request and response more directly. @@ -155,6 +155,90 @@ Consider this example from the Wagtail demo site's ``models.py``, which serves a With this strategy, you could use Django or Python utilities to render your model in JSON or XML or any other format you'd like. + +Adding Endpoints with Custom route() Methods +-------------------------------------------- + +Wagtail routes requests by iterating over the path components (separated with a forward slash ``/``), finding matching objects based on their slug, and delegating further routing to that object's model class. The Wagtail source is very instructive in figuring out what's happening. This is the default ``route()`` method of the ``Page`` class: + +.. code-block:: python + + class Page(...): + + ... + + def route(self, request, path_components): + if path_components: + # request is for a child of this page + child_slug = path_components[0] + remaining_components = path_components[1:] + + # find a matching child or 404 + try: + subpage = self.get_children().get(slug=child_slug) + except Page.DoesNotExist: + raise Http404 + + # delegate further routing + return subpage.specific.route(request, remaining_components) + + else: + # request is for this very page + if self.live: + # use the serve() method to render the request if the page is published + return self.serve(request) + else: + # the page matches the request, but isn't published, so 404 + raise Http404 + +The contract is pretty simple. ``route()`` takes the current object (``self``), the ``request`` object, and a list of the remaining ``path_components`` from the request URL. It either continues delegating routing by calling ``route()`` again on one of its children in the Wagtail tree, or ends the routing process by serving something -- either normally through the ``self.serve()`` method or by raising a 404 error. + +By overriding the ``route()`` method, we could create custom endpoints for each object in the Wagtail tree. One use case might be using an alternate template when encountering the ``print/`` endpoint in the path. Another might be a REST API which interacts with the current object. Just to see what's involved, lets make a simple model which prints out all of its child path components. + +First, ``models.py``: + +.. code-block:: python + + from django.shortcuts import render + + ... + + class Echoer(Page): + + def route(self, request, path_components): + if path_components: + return render(request, self.template, { + 'self': self, + 'echo': ' '.join(path_components), + }) + else: + if self.live: + return self.serve(request) + else: + raise Http404 + + Echoer.content_panels = [ + FieldPanel('title', classname="full title"), + ] + + Echoer.promote_panels = [ + MultiFieldPanel(COMMON_PANELS, "Common page configuration"), + ] + +This model, ``Echoer``, doesn't define any properties, but does subclass ``Page`` so objects will be able to have a custom title and slug. The template just has to display our ``{{ echo }}`` property. We're skipping the ``serve()`` method entirely, but you could include your render code there to stay consistent with Wagtail's conventions. + +Now, once creating a new ``Echoer`` page in the Wagtail admin titled "Echo Base," requests such as:: + + http://127.0.0.1:8000/echo-base/tauntaun/kennel/bed/and/breakfast/ + +Will return:: + + tauntaun kennel bed and breakfast + +Lovely, huh? (We know.) + + + Tagging ------- @@ -216,10 +300,10 @@ This is just one possible way of creating a taxonomy for Wagtail objects. With a - custom route methods - ParentalKey for storing groups of stuff to a Page-thing +Extended Page Data with ParentalKey +----------------------------------- @@ -229,11 +313,23 @@ Templates Location -------- - Wagtail looks for templates matching your models in... + +For each of your ``Page``-derived models, Wagtail will look for a template in the following location, relative to your project root:: + + project/ + app/ + templates/ + app/ + blog_index_page.html + models.py + +Class names are converted from camel case to underscores. For example, the template for model class ``BlogIndexPage`` would be assumed to be ``blog_index_page.html``. Self ---- - Without a custom rendering function, a ... + +By default, the context passed to a model's template consists of two properties: ``self`` and ``request``. ``self`` is the model object being displayed. ``request`` is the normal Django request object. + Template Tags ------------- From da2c69a5ee3820f5763ae8b2a1f898e4e2190ab0 Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Thu, 15 May 2014 22:50:26 -0400 Subject: [PATCH 31/57] Routes --- docs/building_your_site.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/building_your_site.rst b/docs/building_your_site.rst index 04c2e2ae5..7cb2f04a5 100644 --- a/docs/building_your_site.rst +++ b/docs/building_your_site.rst @@ -302,9 +302,15 @@ This is just one possible way of creating a taxonomy for Wagtail objects. With a -Extended Page Data with ParentalKey +Page Data Clusters with ParentalKey ----------------------------------- +The ``django-modelcluster`` module allows for streamlined relation of extra models to a Wagtail page. + + + + + From 04e56198ffc186352b0693f6b8180e7bb37fcd5c Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Fri, 16 May 2014 12:02:32 -0400 Subject: [PATCH 32/57] placeholders added --- docs/building_your_site.rst | 75 +++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/docs/building_your_site.rst b/docs/building_your_site.rst index 36d264048..28fbd7010 100644 --- a/docs/building_your_site.rst +++ b/docs/building_your_site.rst @@ -178,50 +178,51 @@ Location Self ---- - Without a custom rendering function, a + +Without a custom rendering function, the ``Page`` class will provide a ``self`` variable which a template can use to display Tags Provided by Wagtail ------------------------ - pageurl - Loaded into a template with - {% load pageurl %} - Used like - - Given a Page-derived class, outputs a page's URL as relative (/foo/bar/) if it's within the same site as the current page, or absolute (http://example.com/foo/bar/) if not. - slugurl - Loaded into a template with - {% load slugurl %} - Used like - - Returns the URL for the page that has the given slug. Like pageurl, will try to provide a relative link if possible, but will default to an absolute link if on a different site. - wagtailuserbar - Loaded into a template with - {% load wagtailuserbar %} - Used like - {% wagtailuserbar %} - This tag provides a Wagtail icon and flyout menu on the top-right of a page for a logged-in user with editing capabilities, with the option of editing the current Page-derived object or adding a new sibling object. - image - Loaded with - {% load image_tags %} - Used with - {% image self.photo max-320x200 %} - {% image self.photo max-320x200 as img %} - This template tag provides a way to process an image with a method and dimensions +``pageurl`` + Loaded into a template with + ``{% load pageurl %}`` + Used like + ```` + Given a Page-derived class, outputs a page's URL as relative (/foo/bar/) if it's within the same site as the current page, or absolute (http://example.com/foo/bar/) if not. +``slugurl`` + Loaded into a template with + ``{% load slugurl %}`` + Used like + ```` + Returns the URL for the page that has the given slug. Like pageurl, will try to provide a relative link if possible, but will default to an absolute link if on a different site. +``wagtailuserbar`` + Loaded into a template with + ``{% load wagtailuserbar %}`` + Used like + ``{% wagtailuserbar %}`` + This tag provides a Wagtail icon and flyout menu on the top-right of a page for a logged-in user with editing capabilities, with the option of editing the current Page-derived object or adding a new sibling object. +``image`` + Loaded with + ``{% load image_tags %}`` + Used with + ``{% image self.photo max-320x200 %}`` + ``{% image self.photo max-320x200 as img %}`` + This template tag provides a way to process an image with a method and dimensions - 'max': 'resize_to_max', - 'min': 'resize_to_min', - 'width': 'resize_to_width', - 'height': 'resize_to_height', - 'fill': 'resize_to_fill', + 'max': 'resize_to_max', + 'min': 'resize_to_min', + 'width': 'resize_to_width', + 'height': 'resize_to_height', + 'fill': 'resize_to_fill', Filters Provided by Wagtail --------------------------- - rich_text + ``rich_text`` Loaded into template with - {% load rich_text %} + ``{% load rich_text %}`` Used with - {{ body|richtext }} + ``{{ body|richtext }}`` This filter is required for use with any RichTextField, because it will expand internal shorthand references to embeds and links made in the Wagtail editor into fully-baked HTML ready for display. @@ -234,11 +235,11 @@ Advanced Wagtail wagtail user bar custom CSS option? +extending hallo editor plugins with editor_js() +injecting any JS into page edit with editor_js() - - - +Custom content module (same level as docs or images) From 62f3ecaa9ba27393c4173f13aa07e24eb83f3370 Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Fri, 16 May 2014 12:10:46 -0400 Subject: [PATCH 33/57] another placeholder --- docs/panels.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/panels.rst b/docs/panels.rst index 7cf6c1056..47cd3e1a7 100644 --- a/docs/panels.rst +++ b/docs/panels.rst @@ -29,5 +29,8 @@ DocumentChooserPanel SnippetChooserPanel ~~~~~~~~~~~~~~~~~~~ +Custom Panels +~~~~~~~~~~~~~ + From 446c053a170bf5099a64e2e7438033c7d305a7be Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Sat, 17 May 2014 20:54:36 -0400 Subject: [PATCH 34/57] more model basics --- docs/building_your_site.rst | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/docs/building_your_site.rst b/docs/building_your_site.rst index e49c86360..a6677a88a 100644 --- a/docs/building_your_site.rst +++ b/docs/building_your_site.rst @@ -36,10 +36,44 @@ The ``Page`` class actually has alot more to it, but these are probably the only Anatomy of a Wagtail Model ~~~~~~~~~~~~~~~~~~~~~~~~~~ -So what does a Wagtail model definition look like? +So what does a Wagtail model definition look like? Here's a model representing a typical blog post: +.. code-block:: python + from django.db import models + from wagtail.wagtailcore.models import Page + from wagtail.wagtailcore.fields import RichTextField + from wagtail.wagtailadmin.edit_handlers import FieldPanel + from wagtail.wagtailimages.edit_handlers import ImageChooserPanel + from wagtail.wagtailimages.models import Image + + class BlogPage(Page): + body = RichTextField() + date = models.DateField("Post date") + feed_image = models.ForeignKey( + 'wagtailimages.Image', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+' + ) + + BlogPage.content_panels = [ + FieldPanel('title', classname="full title"), + FieldPanel('date'), + FieldPanel('body', classname="full"), + ] + + BlogPage.promote_panels = [ + FieldPanel('slug'), + FieldPanel('seo_title'), + FieldPanel('show_in_menus'), + FieldPanel('search_description'), + ImageChooserPanel('feed_image'), + ] + +To keep track of your ``Page``-derived models, it might be helpful to include "Page" as the last part of your classname. ``BlogPage`` defines three properties: ``body``, ``date``, and ``feed_image``. These are a mix of basic Django models (``date``) and Wagtail models (``feed_image`` and ``body``). From bfc53dd6ce9c1fc82fa6383b04d42fc3c1d3a54a Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Sun, 18 May 2014 01:21:17 -0400 Subject: [PATCH 35/57] added request lifestyle introduction --- docs/building_your_site.rst | 38 ++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/docs/building_your_site.rst b/docs/building_your_site.rst index a6677a88a..2768cb9cf 100644 --- a/docs/building_your_site.rst +++ b/docs/building_your_site.rst @@ -1,7 +1,13 @@ Building your site ================== -Wagtail manages content internally as a tree of pages. Each node in the tree is an instance of a Django model which subclasses the Wagtail ``Page`` class. You define the structure and interrelationships of your Wagtail site by coding these models and then publishing pages which use the models through the Wagtail admin interface. +Wagtail requires a little careful setup to define the types of content that you want to present through your website. The basic unit of content in Wagtail is the ``Page``, and all of your page-level content will inherit basic webpage-related properties from it. But for the most part, you will be defining content yourself, through the contruction of Django models using Wagtail's ``Page`` as a base. + +Wagtail organizes content created from your models in a tree, which can have any structure and combination of model objects in it. Wagtail doesn't prescribe ways to organize and interrelate your content, but here we've sketched out some strategies for organizing your models. + +The presentation of your content, the actual webpages, includes the normal use of the Django template system. We'll cover additional functionality that Wagtail provides at the template level later on. + +But first, we'll take a look at the ``Page`` class and model definitions. The Page Class @@ -73,17 +79,17 @@ So what does a Wagtail model definition look like? Here's a model representing a ImageChooserPanel('feed_image'), ] -To keep track of your ``Page``-derived models, it might be helpful to include "Page" as the last part of your classname. ``BlogPage`` defines three properties: ``body``, ``date``, and ``feed_image``. These are a mix of basic Django models (``date``) and Wagtail models (``feed_image`` and ``body``). - - - +To keep track of your ``Page``-derived models, it might be helpful to include "Page" as the last part of your classname. ``BlogPage`` defines three properties: ``body``, ``date``, and ``feed_image``. These are a mix of basic Django models (``DateField``), Wagtail fields (``RichTextField``), and a pointer to a Wagtail model (``Image``). +Next, the ``content_panels`` and ``promote_panels`` lists define the capabilities and layout of the Wagtail admin page edit interface. The lists are filled with "panels" and "choosers", which will provide a fine-grain interface for inputting the model's content. The ``ImageChooserPanel``, for instance, lets one browse the image library, upload new images, and input image metadata. The ``RichTextField`` is the basic field for creating web-ready website rich text, including text formatting and embedded media like images and video. The Wagtail admin offers other choices for fields, Panels, and Choosers, with the option of creating your own to precisely fit your content without workarounds or other compromises. +Your models may be even more complex, with methods overriding the built-in functionality of the ``Page`` to achieve webdev magic. Or, you can keep your models simple and let Wagtail's built-in functionality do the work. +Now that we have a basic idea of how our content is defined, lets look at relationships between pieces of content. Introduction to Trees ---------------------- +~~~~~~~~~~~~~~~~~~~~~ If you're unfamiliar with trees as an abstract data type, you might want to `review the concepts involved. `_ @@ -105,6 +111,7 @@ Nodes and Leaves It might be handy to think of the ``Page``-derived models you want to create as being one of two node types: parents and leaves. Wagtail isn't prescriptive in this approach, but it's a good place to start if you're not experienced in structuring your own content types. + Nodes ````` Parent nodes on the Wagtail tree probably want to organize and display a browsable index of their descendents. A blog, for instance, needs a way to show a list of individual posts. @@ -125,6 +132,7 @@ A Parent node could provide its own function returning its descendant objects. This example makes sure to limit the returned objects to pieces of content which make sense, specifically ones which have been published through Wagtail's admin interface (``live=True``) and are descendants of this node. Wagtail will allow the "illogical" placement of child nodes under a parent, so it's necessary for a parent model to index only those children which make sense. + Leaves `````` Leaves are the pieces of content itself, a page which is consumable, and might just consist of a bunch of properties. A blog page leaf might have some body text and an image. A person page leaf might have a photo, a name, and an address. @@ -148,6 +156,7 @@ The model for the leaf could provide a function that traverses the tree in the o Since Wagtail doesn't limit what Page-derived classes can be assigned as parents and children, the reverse tree traversal needs to accommodate cases which might not be expected, such as the lack of a "logical" parent to a leaf. + Other Relationships ``````````````````` Your ``Page``-derived models might have other interrelationships which extend the basic Wagtail tree or depart from it entirely. You could provide functions to navigate between siblings, such as a "Next Post" link on a blog page (``post->post->post``). It might make sense for subtrees to interrelate, such as in a discussion forum (``forum->post->replies``) Skipping across the hierarchy might make sense, too, as all objects of a certain model class might interrelate regardless of their ancestors (``events = EventPage.objects.all``). Since there's no restriction on the combination of model classes that can be used at any point in the tree, and it's largely up to the models to define their interrelations, the possibilities are really endless. @@ -155,8 +164,16 @@ Your ``Page``-derived models might have other interrelationships which extend th Anatomy of a Wagtail Request ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -route() -> serve() -> render() -> template +For going beyond the basics of model definition and interrelation, it might help to know how Wagtail handles requests and constructs responses. In short, it goes something like: + + #. Django gets a request and routes through Wagtail's URL dispatcher definitions + #. Starting from the root content piece, Wagtail traverses the page tree, letting the model for each piece of content along the path decide how to ``route()`` the next step in the path. + #. A model class decides that routing is done and it's now time to ``serve()`` content. + #. The model constructs a context, finds a template to pass it to, and renders the content. + #. The templates are rendered and the response object is sent back to the requester. + +You can apply custom behavior to this process by overriding the ``route()`` and ``serve()`` methods of the ``Page`` class in your own models. Model Recipes @@ -339,9 +356,6 @@ Iterating through ``self.tags.all`` will display each tag associated with ``self This is just one possible way of creating a taxonomy for Wagtail objects. With all of the components for a taxonomy available through Wagtail, you should be able to fulfill even the most exotic taxonomic schemes. - - - Page Data Clusters with ParentalKey ----------------------------------- @@ -369,7 +383,9 @@ For each of your ``Page``-derived models, Wagtail will look for a template in th blog_index_page.html models.py -Class names are converted from camel case to underscores. For example, the template for model class ``BlogIndexPage`` would be assumed to be ``blog_index_page.html``. +Class names are converted from camel case to underscores. For example, the template for model class ``BlogIndexPage`` would be assumed to be ``blog_index_page.html``. For more information, see the Django documentation for the `application directories template loader`_. + +.. _application directories template loader: https://docs.djangoproject.com/en/dev/ref/templates/api/ Self From 73fa1000b138cfc9b0c8ca4527c392fa685e4f3f Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Mon, 19 May 2014 21:14:45 -0400 Subject: [PATCH 36/57] editing api started --- docs/editing_api.rst | 119 +++++++++++++++++++++++++++++++++++++++++++ docs/index.rst | 2 +- docs/panels.rst | 36 ------------- 3 files changed, 120 insertions(+), 37 deletions(-) create mode 100644 docs/editing_api.rst delete mode 100644 docs/panels.rst diff --git a/docs/editing_api.rst b/docs/editing_api.rst new file mode 100644 index 000000000..99791c333 --- /dev/null +++ b/docs/editing_api.rst @@ -0,0 +1,119 @@ + +Wagtail Editing API +=================== + +Wagtail provides a highly-customizable editing interface consisting of several components: + + * **Fields** — built-in content types to augment the basic types provided by Django. + * **Field Widgets** — editing widgets which streamline data input + * **Panels** — containers which hold related field widgets + * **Choosers** — interfaces for finding related objects in a ForeignKey relationship + +Configuring your models to use these components will shape the Wagtail editor to your needs. Wagtail also provides an API for injecting custom CSS and Javascript for further customization, including extending the hallo.js rich text editor. + +There is also an Edit Handler API for creating your own Wagtail editor components. + + +Fields +~~~~~~ + +Django's field types are automatically recognized and provided with an appropriate widget for input. + + +``RichTextField`` + + body = RichTextField() + +``Image`` + + feed_image = models.ForeignKey( + 'wagtailimages.Image', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+' + ) + +``Document`` + + link_document = models.ForeignKey( + 'wagtaildocs.Document', + null=True, + blank=True, + related_name='+' + ) + +``Page`` + + page = models.ForeignKey( + 'wagtailcore.Page', + related_name='adverts', + null=True, + blank=True + ) + +Can also use more specific models. + + +Snippets + +Snippets are not not subclasses, so you must include the model class directly. A chooser is provided which takes the snippet class. + + advert = models.ForeignKey( + 'demo.Advert', + related_name='+' + ) + + +Panels +~~~~~~ + + + + + + + + + + + +FieldPanel +~~~~~~~~~~ +Takes field_name, classname=None + + +MultiFieldPanel +~~~~~~~~~~~~~~~ +Condenses several ``FieldPanel``s under a single heading and classname. + + +InlinePanel +~~~~~~~~~~~ +Allows for creating/editing a modelcluster of related objects (carousel example). + + + +RichTextFieldPanel +~~~~~~~~~~~~~~~~~~ + + + + +PageChooserPanel +~~~~~~~~~~~~~~~~ + +ImageChooserPanel +~~~~~~~~~~~~~~~~~ + +DocumentChooserPanel +~~~~~~~~~~~~~~~~~~~~ + +SnippetChooserPanel +~~~~~~~~~~~~~~~~~~~ + +Edit Handler API +~~~~~~~~~~~~~~~~ + + + diff --git a/docs/index.rst b/docs/index.rst index defbe99cf..9717326d4 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -10,7 +10,7 @@ It supports Django 1.6.2+ on Python 2.6 and 2.7. Django 1.7 and Python 3 support gettingstarted building_your_site - panels + editing_api snippets wagtail_search advanced_topics diff --git a/docs/panels.rst b/docs/panels.rst deleted file mode 100644 index 47cd3e1a7..000000000 --- a/docs/panels.rst +++ /dev/null @@ -1,36 +0,0 @@ - -Panels & Edit Handlers -====================== - -RichTextField -~~~~~~~~~~~~~ - -Image -~~~~~ - -FieldPanel -~~~~~~~~~~ - -MultiFieldPanel -~~~~~~~~~~~~~~~ - -InlinePanel -~~~~~~~~~~~ - -PageChooserPanel -~~~~~~~~~~~~~~~~ - -ImageChooserPanel -~~~~~~~~~~~~~~~~~ - -DocumentChooserPanel -~~~~~~~~~~~~~~~~~~~~ - -SnippetChooserPanel -~~~~~~~~~~~~~~~~~~~ - -Custom Panels -~~~~~~~~~~~~~ - - - From b6788f7c66bf13c7b418d6fcecf40c2e9afda6d8 Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Tue, 20 May 2014 23:34:47 -0400 Subject: [PATCH 37/57] Editing API docs looking better at least --- docs/building_your_site.rst | 3 - docs/editing_api.rst | 193 ++++++++++++++++++++++++------------ 2 files changed, 132 insertions(+), 64 deletions(-) diff --git a/docs/building_your_site.rst b/docs/building_your_site.rst index 2768cb9cf..2f010ba8c 100644 --- a/docs/building_your_site.rst +++ b/docs/building_your_site.rst @@ -356,10 +356,7 @@ Iterating through ``self.tags.all`` will display each tag associated with ``self This is just one possible way of creating a taxonomy for Wagtail objects. With all of the components for a taxonomy available through Wagtail, you should be able to fulfill even the most exotic taxonomic schemes. -Page Data Clusters with ParentalKey ------------------------------------ -The ``django-modelcluster`` module allows for streamlined relation of extra models to a Wagtail page. diff --git a/docs/editing_api.rst b/docs/editing_api.rst index 99791c333..8fcb0b715 100644 --- a/docs/editing_api.rst +++ b/docs/editing_api.rst @@ -1,72 +1,146 @@ -Wagtail Editing API -=================== +Editing API +=========== Wagtail provides a highly-customizable editing interface consisting of several components: - * **Fields** — built-in content types to augment the basic types provided by Django. - * **Field Widgets** — editing widgets which streamline data input - * **Panels** — containers which hold related field widgets - * **Choosers** — interfaces for finding related objects in a ForeignKey relationship + * **Fields** — built-in content types to augment the basic types provided by Django. + * **Panels** — the basic editing blocks for fields, groups of fields, and related object clusters + * **Choosers** — interfaces for finding related objects in a ForeignKey relationship Configuring your models to use these components will shape the Wagtail editor to your needs. Wagtail also provides an API for injecting custom CSS and Javascript for further customization, including extending the hallo.js rich text editor. There is also an Edit Handler API for creating your own Wagtail editor components. -Fields -~~~~~~ +Defining Panels +~~~~~~~~~~~~~~~ -Django's field types are automatically recognized and provided with an appropriate widget for input. +A "panel" is the basic editing block in Wagtail. Wagtail will automatically pick the appropriate editing widget for most Django field types, you just need to add a panel for each field you want to show in the Wagtail page editor, in the order you want them to appear. + +There are three types of panels: + + ``FieldPanel( field_name, classname=None )`` + This is the panel used for basic Django field types. ``field_name`` is the name of the class property used in your model definition. ``classname`` is a string of optional CSS classes given to the panel which are used in formatting and scripted interactivity. By default, panels are formatted as inset fields. The CSS class ``full`` can be used to format the panel so it covers the full width of the Wagtail page editor. The CSS class ``title`` can be used to mark a field as the source for auto-generated slug strings. + + ``MultiFieldPanel( panel_list, heading )`` + This panel condenses several ``FieldPanel`` s or choosers, from a list or tuple, under a single ``heading`` string. + + ``InlinePanel( base_model, relation_name, panels=None, label='', help_text='' )`` + This panel allows for the creation of a "cluster" of related objects over a join to a separate model, such as a list of related links or slides to an image carousel. This is a very powerful, but tricky feature which will take some space to cover, so we'll skip over it for now. For a full explaination on the usage of ``InlinePanel``, see :ref:`inline_panels`. + +Wagtail provides a tabbed interface to help organize panels. ``content_panels`` is the main tab, used for the meat of your model content. The other, ``promote_panels``, is suggested for organizing metadata about the content, such as SEO information and other machine-readable information. Since you're writing the panel definitions, you can organize them however you want. + +Let's look at an example of a panel definition: + +.. code-block:: python + + COMMON_PANELS = ( + FieldPanel('slug'), + FieldPanel('seo_title'), + FieldPanel('show_in_menus'), + FieldPanel('search_description'), + ) + + ... + + class ExamplePage( Page ): + # field definitions omitted + ... + + ExamplePage.content_panels = [ + FieldPanel('title', classname="full title"), + FieldPanel('body', classname="full"), + FieldPanel('date'), + ImageChooserPanel('splash_image'), + DocumentChooserPanel('free_download'), + PageChooserPanel('related_page'), + ] + + ExamplePage.promote_panels = [ + MultiFieldPanel(COMMON_PANELS, "Common page configuration"), + ] -``RichTextField`` - body = RichTextField() -``Image`` - feed_image = models.ForeignKey( - 'wagtailimages.Image', - null=True, - blank=True, - on_delete=models.SET_NULL, - related_name='+' - ) +Built-in Fields and Choosers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -``Document`` +Django's field types are automatically recognized and provided with an appropriate widget for input. Just define that field the normal Django way and pass the field name into ``FieldPanel()`` when defining your panels. Wagtail will take care of the rest. - link_document = models.ForeignKey( - 'wagtaildocs.Document', - null=True, - blank=True, - related_name='+' - ) +Here are some Wagtail-specific types that you might include as fields in your models. -``Page`` - page = models.ForeignKey( - 'wagtailcore.Page', - related_name='adverts', - null=True, - blank=True - ) +Rich Text (HTML) +---------------- + +Wagtail provides a general-purpose WYSIWYG editor for creating rich text content (HTML) and embedding media such as images, video, and documents. To include this in your models, use the ``RichTextField()`` function when defining a model field: + +.. code-block:: python + + from wagtail.wagtailcore.fields import RichTextField + ... + class BookPage(Page): + book_text = RichTextField() + + + +If you're interested in extending the capabilities of the Wagtail editor, See :ref:`extending_wysiwyg`. + + +Images +------ + + from wagtail.wagtailimages.models import Image + + feed_image = models.ForeignKey( + 'wagtailimages.Image', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+' + ) + + +Documents +--------- + + from wagtail.wagtaildocs.models import Document + + link_document = models.ForeignKey( + 'wagtaildocs.Document', + null=True, + blank=True, + related_name='+' + ) + + +Pages and Page-derived Models +----------------------------- + + from wagtail.wagtailcore.models import Page + + page = models.ForeignKey( + 'wagtailcore.Page', + related_name='+', + null=True, + blank=True + ) Can also use more specific models. -Snippets +Snippets (and Basic Django Models?) +-------- Snippets are not not subclasses, so you must include the model class directly. A chooser is provided which takes the snippet class. - advert = models.ForeignKey( - 'demo.Advert', - related_name='+' - ) - - -Panels -~~~~~~ + advert = models.ForeignKey( + 'demo.Advert', + related_name='+' + ) @@ -78,25 +152,6 @@ Panels -FieldPanel -~~~~~~~~~~ -Takes field_name, classname=None - - -MultiFieldPanel -~~~~~~~~~~~~~~~ -Condenses several ``FieldPanel``s under a single heading and classname. - - -InlinePanel -~~~~~~~~~~~ -Allows for creating/editing a modelcluster of related objects (carousel example). - - - -RichTextFieldPanel -~~~~~~~~~~~~~~~~~~ - @@ -112,6 +167,22 @@ DocumentChooserPanel SnippetChooserPanel ~~~~~~~~~~~~~~~~~~~ + +.. _inline_panels: + +Inline Panels and Model Clusters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``django-modelcluster`` module allows for streamlined relation of extra models to a Wagtail page. + + +.. _extending_wysiwyg: + +Extending the WYSIWYG Editor (hallo.js) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + Edit Handler API ~~~~~~~~~~~~~~~~ From 18df9e094cc37c5b274cda91df9117300c83a028 Mon Sep 17 00:00:00 2001 From: Dave Cranwell Date: Thu, 22 May 2014 14:26:09 +0100 Subject: [PATCH 38/57] tweaked font size of userbar icons, it got reduced accidentally during previous changes accidentally --- wagtail/wagtailadmin/static/wagtailadmin/scss/userbar.scss | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wagtail/wagtailadmin/static/wagtailadmin/scss/userbar.scss b/wagtail/wagtailadmin/static/wagtailadmin/scss/userbar.scss index 84b99b537..af9e20195 100644 --- a/wagtail/wagtailadmin/static/wagtailadmin/scss/userbar.scss +++ b/wagtail/wagtailadmin/static/wagtailadmin/scss/userbar.scss @@ -87,11 +87,13 @@ li, .home{ .action{ @include transition(background-color 0.2s ease, color 0.2s ease); background-color:$color-teal; - color:white; + color:$color-teal; &:before{ margin-right:0.4em; vertical-align:middle; + font-size:1.7em; + color:white; } &:hover{ From b9c7c871dd8d55593456d99494cc286d322e68dd Mon Sep 17 00:00:00 2001 From: Dave Cranwell Date: Thu, 22 May 2014 17:19:40 +0100 Subject: [PATCH 39/57] adding incomplete front end developer documentation --- docs/building_your_site/djangodevelopers.rst | 3 + .../building_your_site/frontenddevelopers.rst | 117 ++++++++++++++++++ .../index.rst} | 11 +- docs/editor_manual/index.rst | 5 +- docs/index.rst | 2 +- 5 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 docs/building_your_site/djangodevelopers.rst create mode 100644 docs/building_your_site/frontenddevelopers.rst rename docs/{building_your_site.rst => building_your_site/index.rst} (59%) diff --git a/docs/building_your_site/djangodevelopers.rst b/docs/building_your_site/djangodevelopers.rst new file mode 100644 index 000000000..62f37c12b --- /dev/null +++ b/docs/building_your_site/djangodevelopers.rst @@ -0,0 +1,3 @@ +For Django developers +================== + diff --git a/docs/building_your_site/frontenddevelopers.rst b/docs/building_your_site/frontenddevelopers.rst new file mode 100644 index 000000000..f6b676d1f --- /dev/null +++ b/docs/building_your_site/frontenddevelopers.rst @@ -0,0 +1,117 @@ +For Front End developers +======================== + +.. note:: + This documentation is currently being written. + +======================== +Overview +======================== + +Wagtail uses Django's templating language. For developers new to Django, start with Django's own template documentation: +https://docs.djangoproject.com/en/dev/topics/templates/ + +Python programmers new to Django/Wagtail may prefer more technical documentation: +https://docs.djangoproject.com/en/dev/ref/templates/api/ + +======================== +Page content and variables +======================== + + +======================== +Static files (css, js, images) +======================== + + + +Images +~~~~~~~~~~ + +Images uploaded to Wagtail go into the image library and from there are added to pages via the :doc:`page editor interface `. + +Unlike other CMS, adding images to a page does not involve choosing a "version" of the image to use. Wagtail has no predefined image "formats" or "sizes". Instead the template developer defines image manipulation to occur *on the fly* when the image is requested, via a special syntax within the template. + +Images from the library **must** be requested using this syntax, but images in your codebase can be added via conventional means e.g ``img`` tags. Only images from the library can be manipulated on the fly. + +Read more about the image manipulation syntax here :ref:`Images tag `. + + +======================== +Template tags & filters +======================== + +In addition to Django's standard tags and filters, Wagtail provides some of it's own, which can be ``load``-ed `as you would any other `_ + +.. _image-tag: +Images (tag) +~~~~~~~~~~~~ + +The syntax for displaying/manipulating an image is thus:: + + {% image [image] [method]-[dimension(s)] %} + +The ``image`` is the Django object refering to the image. If your page model defined a field called "photo" then ``image`` would probably be ``self.photo``. The ``method`` defines which resizing algorithm to use and ``dimension(s)`` provides height and/or width values (as ``[height]`` or ``[width]x[height]``) to refine that algorithm. + +Note that a space separates ``image`` and ``method``, but not ``method`` and ``dimensions``. A hyphen between ``width`` and ``dimensions`` is mandatory. + +The available ``method`` s are: + +.. glossary:: + ``max`` + (takes two dimensions) + + Fit **within** the given dimensions. + + The longest edge will be reduced to the equivalent dimension size defined. e.g A portrait image of width 1000, height 2000, treated with the ``max`` dimensions ``1000x500`` (landscape) would result in the image shrunk so the *height* was 500 pixels and the width 250. + + ``min`` + (takes two dimensions) + + **Cover** the given dimensions. + + This may result in an image slightly **larger** than the dimensions you specify. e.g A square image of width 2000, height 2000, treated with the ``min`` dimensions ``500x200`` (landscape) would have it's height and width changed to 500, i.e matching the width required, but greater than the height. + + ``width`` + (takes one dimension) + + Reduces the width of the image to the dimension specified. + + ``height`` + (takes one dimension) + + Resize the height of the image to the dimension specified.. + + ``fill`` + (takes two dimensions) + + Resize and **crop** to fill the **exact** dimensions. + + This can be particularly useful for websites requiring square thumbnails of arbitrary images. e.g A landscape image of width 2000, height 1000, treated with ``fill`` dimensions ``200x200`` would have it's height reduced to 200, then it's width (ordinarily 400) cropped to 200. + + **The crop always aligns on the centre of the image.** + +.. Note:: + Wagtail *does not allow deforming or stretching images*. Image dimension ratios will always be kept. Wagtail also *does not support upscaling*. Small images forced to appear at larger sizes will "max out" at their their native dimensions. + + +Rich text (filter) +~~~~~~~~~~~~~~~~~~ + + +Internal links (tag) +~~~~~~~~~~~~~~~~~~~~ + + +Static files (tag) +~~~~~~~~~~~~~~ + + +Misc +~~~~~~~~~~ + + +======================== +Wagtail User Bar +======================== + diff --git a/docs/building_your_site.rst b/docs/building_your_site/index.rst similarity index 59% rename from docs/building_your_site.rst rename to docs/building_your_site/index.rst index b506f67f2..fb336e18b 100644 --- a/docs/building_your_site.rst +++ b/docs/building_your_site/index.rst @@ -1,6 +1,15 @@ Building your site ================== +.. note:: + Documentation currently incomplete and in draft status + Serafeim Papastefanos has written a comprehensive tutorial on creating a site from scratch in Wagtail; for the time being, this is our recommended resource: -`spapas.github.io/2014/02/13/wagtail-tutorial/ `_ \ No newline at end of file +`spapas.github.io/2014/02/13/wagtail-tutorial/ `_ + +.. toctree:: + :maxdepth: 3 + + djangodevelopers + frontenddevelopers diff --git a/docs/editor_manual/index.rst b/docs/editor_manual/index.rst index 4562844e7..b7b5c84f7 100644 --- a/docs/editor_manual/index.rst +++ b/docs/editor_manual/index.rst @@ -1,9 +1,10 @@ Using Wagtail: an Editor's guide ================================ -This section of the documentation is written for the users of a Wagtail-powered site. That is, the content editors, moderators and administrators who will be running things on a day-to-day basis. +.. note:: + Documentation currently incomplete and in draft status -**NOTE:** This section of the documentation is currently in draft status. +This section of the documentation is written for the users of a Wagtail-powered site. That is, the content editors, moderators and administrators who will be running things on a day-to-day basis. .. toctree:: :maxdepth: 3 diff --git a/docs/index.rst b/docs/index.rst index dbfe91f33..40510c7da 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -9,7 +9,7 @@ It supports Django 1.6.2+ on Python 2.6 and 2.7. Django 1.7 and Python 3 support :maxdepth: 3 gettingstarted - building_your_site + building_your_site/index wagtail_search deploying performance From 3a42a0eb465a66f0f0125fc920fd4ee7f5c59fa3 Mon Sep 17 00:00:00 2001 From: Dave Cranwell Date: Thu, 22 May 2014 17:27:01 +0100 Subject: [PATCH 40/57] adding incomplete front end developer documentation --- docs/building_your_site/frontenddevelopers.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/building_your_site/frontenddevelopers.rst b/docs/building_your_site/frontenddevelopers.rst index f6b676d1f..a39e6cd0c 100644 --- a/docs/building_your_site/frontenddevelopers.rst +++ b/docs/building_your_site/frontenddevelopers.rst @@ -95,6 +95,9 @@ The available ``method`` s are: Wagtail *does not allow deforming or stretching images*. Image dimension ratios will always be kept. Wagtail also *does not support upscaling*. Small images forced to appear at larger sizes will "max out" at their their native dimensions. +To request the "original" version of an image, it is suggested you use the lack of upscalling support by requesting an image much larger than it's maximum dimensions. e.g to insert an image who's dimensions are uncertain/unknown, at it's maximum size, try: ``{% image self.image width-10000 %}``. This assumes the image is unlikely to be larger than 10000px wide. + + Rich text (filter) ~~~~~~~~~~~~~~~~~~ From 0c92a0009f3014e15e3488f735f0744d60d474ca Mon Sep 17 00:00:00 2001 From: Dave Cranwell Date: Thu, 22 May 2014 17:32:26 +0100 Subject: [PATCH 41/57] updated note about origianl version of image --- docs/building_your_site/frontenddevelopers.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/building_your_site/frontenddevelopers.rst b/docs/building_your_site/frontenddevelopers.rst index a39e6cd0c..276c525ae 100644 --- a/docs/building_your_site/frontenddevelopers.rst +++ b/docs/building_your_site/frontenddevelopers.rst @@ -95,7 +95,7 @@ The available ``method`` s are: Wagtail *does not allow deforming or stretching images*. Image dimension ratios will always be kept. Wagtail also *does not support upscaling*. Small images forced to appear at larger sizes will "max out" at their their native dimensions. -To request the "original" version of an image, it is suggested you use the lack of upscalling support by requesting an image much larger than it's maximum dimensions. e.g to insert an image who's dimensions are uncertain/unknown, at it's maximum size, try: ``{% image self.image width-10000 %}``. This assumes the image is unlikely to be larger than 10000px wide. +To request the "original" version of an image, it is suggested you rely on the lack of upscalling support by requesting an image much larger than it's maximum dimensions. e.g to insert an image who's dimensions are uncertain/unknown, at it's maximum size, try: ``{% image self.image width-10000 %}``. This assumes the image is unlikely to be larger than 10000px wide. Rich text (filter) From 8bacb807ccd75e89a11cfc4e955b8cc2ea61d75f Mon Sep 17 00:00:00 2001 From: Dave Cranwell Date: Thu, 22 May 2014 17:38:43 +0100 Subject: [PATCH 42/57] added better examples --- docs/building_your_site/frontenddevelopers.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/building_your_site/frontenddevelopers.rst b/docs/building_your_site/frontenddevelopers.rst index 276c525ae..f86f09459 100644 --- a/docs/building_your_site/frontenddevelopers.rst +++ b/docs/building_your_site/frontenddevelopers.rst @@ -51,6 +51,13 @@ The syntax for displaying/manipulating an image is thus:: {% image [image] [method]-[dimension(s)] %} +For example:: + + {% image self.photo width-400 %} + + + {% image self.photo fill-80x80 %} + The ``image`` is the Django object refering to the image. If your page model defined a field called "photo" then ``image`` would probably be ``self.photo``. The ``method`` defines which resizing algorithm to use and ``dimension(s)`` provides height and/or width values (as ``[height]`` or ``[width]x[height]``) to refine that algorithm. Note that a space separates ``image`` and ``method``, but not ``method`` and ``dimensions``. A hyphen between ``width`` and ``dimensions`` is mandatory. From 4b07378b89aad825f944035631e90fdc5d4ffa79 Mon Sep 17 00:00:00 2001 From: Dave Cranwell Date: Thu, 22 May 2014 17:40:32 +0100 Subject: [PATCH 43/57] corrected syntax --- docs/building_your_site/frontenddevelopers.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/building_your_site/frontenddevelopers.rst b/docs/building_your_site/frontenddevelopers.rst index f86f09459..7f7a438c1 100644 --- a/docs/building_your_site/frontenddevelopers.rst +++ b/docs/building_your_site/frontenddevelopers.rst @@ -58,7 +58,7 @@ For example:: {% image self.photo fill-80x80 %} -The ``image`` is the Django object refering to the image. If your page model defined a field called "photo" then ``image`` would probably be ``self.photo``. The ``method`` defines which resizing algorithm to use and ``dimension(s)`` provides height and/or width values (as ``[height]`` or ``[width]x[height]``) to refine that algorithm. +The ``image`` is the Django object refering to the image. If your page model defined a field called "photo" then ``image`` would probably be ``self.photo``. The ``method`` defines which resizing algorithm to use and ``dimension(s)`` provides height and/or width values (as ``[width|height]`` or ``[width]x[height]``) to refine that algorithm. Note that a space separates ``image`` and ``method``, but not ``method`` and ``dimensions``. A hyphen between ``width`` and ``dimensions`` is mandatory. From 5f4cc1fa914590204b4fcfe8af27997e79c516e6 Mon Sep 17 00:00:00 2001 From: Dave Cranwell Date: Thu, 22 May 2014 17:47:32 +0100 Subject: [PATCH 44/57] corrected mistake --- docs/building_your_site/frontenddevelopers.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/building_your_site/frontenddevelopers.rst b/docs/building_your_site/frontenddevelopers.rst index 7f7a438c1..1c2268506 100644 --- a/docs/building_your_site/frontenddevelopers.rst +++ b/docs/building_your_site/frontenddevelopers.rst @@ -60,7 +60,7 @@ For example:: The ``image`` is the Django object refering to the image. If your page model defined a field called "photo" then ``image`` would probably be ``self.photo``. The ``method`` defines which resizing algorithm to use and ``dimension(s)`` provides height and/or width values (as ``[width|height]`` or ``[width]x[height]``) to refine that algorithm. -Note that a space separates ``image`` and ``method``, but not ``method`` and ``dimensions``. A hyphen between ``width`` and ``dimensions`` is mandatory. +Note that a space separates ``image`` and ``method``, but not ``method`` and ``dimensions``: a hyphen between ``method`` and ``dimensions`` is mandatory. Multiple dimensions must be separated by an ``x``. The available ``method`` s are: From 99c9d875befca5d6c76a6388a2b4a4bec1fb96c4 Mon Sep 17 00:00:00 2001 From: Tom Dyson Date: Thu, 22 May 2014 17:51:50 +0100 Subject: [PATCH 45/57] Static site generation docs update Formatting tweaks and S3 / Google App Engine options. --- docs/static_site_generation.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/static_site_generation.rst b/docs/static_site_generation.rst index fe4b504ea..a9379cd67 100644 --- a/docs/static_site_generation.rst +++ b/docs/static_site_generation.rst @@ -1,20 +1,20 @@ Generating a static site ======================== -This document describes how to render your Wagtail site into static HTML files using `django medusa`_ and the 'wagtail.contrib.wagtailmedusa' module. +This document describes how to render your Wagtail site into static HTML files on your local filesystem, Amazon S3 or Google App Engine, using `django medusa`_ and the ``wagtail.contrib.wagtailmedusa`` module. Installing django-medusa ~~~~~~~~~~~~~~~~~~~~~~~~ -Firstly, install django medusa from pip: +First, install django medusa from pip: .. code:: pip install django-medusa -Then add 'django_medusa' and 'wagtail.contrib.wagtailmedusa' to INSTALLED_APPS: +Then add ``django_medusa`` and ``wagtail.contrib.wagtailmedusa`` to ``INSTALLED_APPS``: .. code:: python @@ -28,9 +28,9 @@ Then add 'django_medusa' and 'wagtail.contrib.wagtailmedusa' to INSTALLED_APPS: Replacing GET parameters with custom routing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Pages which require GET parameters (eg, pagination) don't generate suitable filenames for generated HTML files so they need to be changed to use custom routing instead. +Pages which require GET parameters (e.g. for pagination) don't generate suitable filenames for generated HTML files so they need to be changed to use custom routing instead. -For example, lets say we have a Blog Index which uses pagination. We can override the 'route' method to make it respond on urls like '/page/1' and pass the page number through to the serve method: +For example, let's say we have a Blog Index which uses pagination. We can override the ``route`` method to make it respond on urls like '/page/1', and pass the page number through to the ``serve`` method: .. code:: python @@ -53,7 +53,7 @@ For example, lets say we have a Blog Index which uses pagination. We can overrid Rendering pages which use custom routing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -For page types that override the route method, we need to let django medusa know which URLs it responds on. This is done by overriding the 'get_static_site_paths' method to make it yield one string per URL path. +For page types that override the ``route`` method, we need to let django medusa know which URLs it responds on. This is done by overriding the ``get_static_site_paths`` method to make it yield one string per URL path. For example, the BlogIndex above would need to yield one URL for each page of results: @@ -75,7 +75,7 @@ For example, the BlogIndex above would need to yield one URL for each page of re Rendering ~~~~~~~~~ -To render a site, just run ``./manage.py staticsitegen``. This will render the entire website and place the HTML in a folder called 'medusa_output'. The static and media folders need to be copied into this folder manually after the rendering is complete. +To render a site, run ``./manage.py staticsitegen``. This will render the entire website and place the HTML in a folder called 'medusa_output'. The static and media folders need to be copied into this folder manually after the rendering is complete. This feature inherits django-medusa's ability to render your static site to Amazon S3 or Google App Engine; see the `medusa docs `_ for configuration details. To test, open the 'medusa_output' folder in a terminal and run ``python -m SimpleHTTPServer``. From cde047f4850770ae0ffd2fcbf0580336bb6cf8ac Mon Sep 17 00:00:00 2001 From: Tom Dyson Date: Thu, 22 May 2014 18:48:14 +0100 Subject: [PATCH 46/57] Getting started docs Less version precision for Ubuntu installs. --- docs/gettingstarted.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/gettingstarted.rst b/docs/gettingstarted.rst index 626aa42c0..a46ea9664 100644 --- a/docs/gettingstarted.rst +++ b/docs/gettingstarted.rst @@ -4,7 +4,7 @@ Getting Started On Ubuntu ~~~~~~~~~ -If you have a fresh instance of Ubuntu 13.04 or 13.10, you can install Wagtail, +If you have a fresh instance of Ubuntu 13.04 or later, you can install Wagtail, along with a demonstration site containing a set of standard templates and page types, in one step. As the root user:: From 779ac271424254e765ea0e0ecf20ba050c451ffa Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Thu, 22 May 2014 19:25:30 -0400 Subject: [PATCH 47/57] Merged with docs coming from torchbox --- docs/advanced_topics.rst | 5 +- docs/building_your_site/djangodevelopers.rst | 188 ++++++- .../building_your_site/frontenddevelopers.rst | 65 ++- docs/building_your_site/index.rst | 485 +----------------- docs/editing_api.rst | 12 + docs/index.rst | 5 +- docs/model_recipes.rst | 176 +++++++ 7 files changed, 447 insertions(+), 489 deletions(-) create mode 100644 docs/model_recipes.rst diff --git a/docs/advanced_topics.rst b/docs/advanced_topics.rst index 1f5cec1bf..7e23d8442 100644 --- a/docs/advanced_topics.rst +++ b/docs/advanced_topics.rst @@ -1,6 +1,9 @@ Advanced Topics ~~~~~~~~~~~~~~~~ +.. note:: + This documentation is currently being written. + replacing image processing backend custom image processing tags? @@ -11,4 +14,4 @@ extending hallo editor plugins with editor_js() injecting any JS into page edit with editor_js() -Custom content module (same level as docs or images) \ No newline at end of file +Custom content module (same level as docs or images) diff --git a/docs/building_your_site/djangodevelopers.rst b/docs/building_your_site/djangodevelopers.rst index 62f37c12b..49f80c371 100644 --- a/docs/building_your_site/djangodevelopers.rst +++ b/docs/building_your_site/djangodevelopers.rst @@ -1,3 +1,189 @@ For Django developers -================== +===================== +.. note:: + This documentation is currently being written. + +Wagtail requires a little careful setup to define the types of content that you want to present through your website. The basic unit of content in Wagtail is the ``Page``, and all of your page-level content will inherit basic webpage-related properties from it. But for the most part, you will be defining content yourself, through the contruction of Django models using Wagtail's ``Page`` as a base. + +Wagtail organizes content created from your models in a tree, which can have any structure and combination of model objects in it. Wagtail doesn't prescribe ways to organize and interrelate your content, but here we've sketched out some strategies for organizing your models. + +The presentation of your content, the actual webpages, includes the normal use of the Django template system. We'll cover additional functionality that Wagtail provides at the template level later on. + +But first, we'll take a look at the ``Page`` class and model definitions. + + +The Page Class +~~~~~~~~~~~~~~ + +``Page`` uses Django's model interface, so you can include any field type and field options that Django allows. Wagtail provides some fields and editing handlers that simplify data entry in the Wagtail admin interface, so you may want to keep those in mind when deciding what properties to add to your models in addition to those already provided by ``Page``. + + +Built-in Properties of the Page Class +------------------------------------- + +Wagtail provides some properties in the ``Page`` class which are common to most webpages. Since you'll be subclassing ``Page``, you don't have to worry about implementing them. + +Public Properties +````````````````` + + ``title`` (string, required) + Human-readable title for the content + + ``slug`` (string, required) + Machine-readable URL component for this piece of content. The name of the page as it will appear in URLs e.g ``http://domain.com/blog/[my-slug]/`` + + ``seo_title`` (string) + Alternate SEO-crafted title which overrides the normal title for use in the ```` of a page + + ``search_description`` (string) + A SEO-crafted description of the content, used in both internal search indexing and for the meta description read by search engines + +The ``Page`` class actually has alot more to it, but these are probably the only built-in properties you'll need to worry about when creating templates for your models. + + +Anatomy of a Wagtail Model +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +So what does a Wagtail model definition look like? Here's a model representing a typical blog post: + +.. code-block:: python + + from django.db import models + + from wagtail.wagtailcore.models import Page + from wagtail.wagtailcore.fields import RichTextField + from wagtail.wagtailadmin.edit_handlers import FieldPanel + from wagtail.wagtailimages.edit_handlers import ImageChooserPanel + from wagtail.wagtailimages.models import Image + + class BlogPage(Page): + body = RichTextField() + date = models.DateField("Post date") + feed_image = models.ForeignKey( + 'wagtailimages.Image', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+' + ) + + BlogPage.content_panels = [ + FieldPanel('title', classname="full title"), + FieldPanel('date'), + FieldPanel('body', classname="full"), + ] + + BlogPage.promote_panels = [ + FieldPanel('slug'), + FieldPanel('seo_title'), + FieldPanel('show_in_menus'), + FieldPanel('search_description'), + ImageChooserPanel('feed_image'), + ] + +To keep track of your ``Page``-derived models, it might be helpful to include "Page" as the last part of your classname. ``BlogPage`` defines three properties: ``body``, ``date``, and ``feed_image``. These are a mix of basic Django models (``DateField``), Wagtail fields (``RichTextField``), and a pointer to a Wagtail model (``Image``). + +Next, the ``content_panels`` and ``promote_panels`` lists define the capabilities and layout of the Wagtail admin page edit interface. The lists are filled with "panels" and "choosers", which will provide a fine-grain interface for inputting the model's content. The ``ImageChooserPanel``, for instance, lets one browse the image library, upload new images, and input image metadata. The ``RichTextField`` is the basic field for creating web-ready website rich text, including text formatting and embedded media like images and video. The Wagtail admin offers other choices for fields, Panels, and Choosers, with the option of creating your own to precisely fit your content without workarounds or other compromises. + +Your models may be even more complex, with methods overriding the built-in functionality of the ``Page`` to achieve webdev magic. Or, you can keep your models simple and let Wagtail's built-in functionality do the work. + +Now that we have a basic idea of how our content is defined, lets look at relationships between pieces of content. + + +Introduction to Trees +~~~~~~~~~~~~~~~~~~~~~ + +If you're unfamiliar with trees as an abstract data type, you might want to `review the concepts involved. `_ + +As a web developer, though, you probably already have a good understanding of trees as filesystem directories or paths. Wagtail pages can create the same structure, as each page in the tree has its own URL path, like so:: + + / + people/ + nien-nunb/ + laura-roslin/ + events/ + captain-picard-day/ + winter-wrap-up/ + +The Wagtail admin interface uses the tree to organize content for editing, letting you navigate up and down levels in the tree through its Explorer menu. This method of organization is a good place to start in thinking about your own Wagtail models. + + +Nodes and Leaves +---------------- + +It might be handy to think of the ``Page``-derived models you want to create as being one of two node types: parents and leaves. Wagtail isn't prescriptive in this approach, but it's a good place to start if you're not experienced in structuring your own content types. + + +Nodes +````` +Parent nodes on the Wagtail tree probably want to organize and display a browsable index of their descendents. A blog, for instance, needs a way to show a list of individual posts. + +A Parent node could provide its own function returning its descendant objects. + +.. code-block:: python + + class EventPageIndex(Page): + ... + def events(self): + # Get list of event pages that are descendants of this page + events = EventPage.objects.filter( + live=True, + path__startswith=self.path + ) + return events + +This example makes sure to limit the returned objects to pieces of content which make sense, specifically ones which have been published through Wagtail's admin interface (``live=True``) and are descendants of this node. Wagtail will allow the "illogical" placement of child nodes under a parent, so it's necessary for a parent model to index only those children which make sense. + + +Leaves +`````` +Leaves are the pieces of content itself, a page which is consumable, and might just consist of a bunch of properties. A blog page leaf might have some body text and an image. A person page leaf might have a photo, a name, and an address. + +It might be helpful for a leaf to provide a way to back up along the tree to a parent, such as in the case of breadcrumbs navigation. The tree might also be deep enough that a leaf's parent won't be included in general site navigation. + +The model for the leaf could provide a function that traverses the tree in the opposite direction and returns an appropriate ancestor: + +.. code-block:: python + + class BlogPage(Page): + ... + def blog_index(self): + # Find blog index in ancestors + for ancestor in reversed(self.get_ancestors()): + if isinstance(ancestor.specific, BlogIndexPage): + return ancestor + + # No ancestors are blog indexes, just return first blog index in database + return BlogIndexPage.objects.first() + +Since Wagtail doesn't limit what Page-derived classes can be assigned as parents and children, the reverse tree traversal needs to accommodate cases which might not be expected, such as the lack of a "logical" parent to a leaf. + + +Other Relationships +``````````````````` +Your ``Page``-derived models might have other interrelationships which extend the basic Wagtail tree or depart from it entirely. You could provide functions to navigate between siblings, such as a "Next Post" link on a blog page (``post->post->post``). It might make sense for subtrees to interrelate, such as in a discussion forum (``forum->post->replies``) Skipping across the hierarchy might make sense, too, as all objects of a certain model class might interrelate regardless of their ancestors (``events = EventPage.objects.all``). Since there's no restriction on the combination of model classes that can be used at any point in the tree, and it's largely up to the models to define their interrelations, the possibilities are really endless. + + +Anatomy of a Wagtail Request +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For going beyond the basics of model definition and interrelation, it might help to know how Wagtail handles requests and constructs responses. In short, it goes something like: + + #. Django gets a request and routes through Wagtail's URL dispatcher definitions + #. Starting from the root content piece, Wagtail traverses the page tree, letting the model for each piece of content along the path decide how to ``route()`` the next step in the path. + #. A model class decides that routing is done and it's now time to ``serve()`` content. + #. The model constructs a context, finds a template to pass it to, and renders the content. + #. The templates are rendered and the response object is sent back to the requester. + +You can apply custom behavior to this process by overriding the ``route()`` and ``serve()`` methods of the ``Page`` class in your own models. + + +Site +~~~~ + +Django's built-in admin interface provides the way to map a "site" (hostname or domain) to any node in the wagtail tree, using that node as the site's root. + +Access this by going to ``/django-admin/`` and then "Home › Wagtailcore › Sites." To try out a development site, add a single site with the hostname ``localhost`` at port ``8000`` and map it to one of the pieces of content you have created. + +Wagtail's developers plan to move the site settings into the Wagtail admin interface. diff --git a/docs/building_your_site/frontenddevelopers.rst b/docs/building_your_site/frontenddevelopers.rst index 1c2268506..033c64e9e 100644 --- a/docs/building_your_site/frontenddevelopers.rst +++ b/docs/building_your_site/frontenddevelopers.rst @@ -14,10 +14,31 @@ https://docs.djangoproject.com/en/dev/topics/templates/ Python programmers new to Django/Wagtail may prefer more technical documentation: https://docs.djangoproject.com/en/dev/ref/templates/api/ -======================== -Page content and variables -======================== +========================== +Displaying Pages +========================== +Template Location +----------------- + +For each of your ``Page``-derived models, Wagtail will look for a template in the following location, relative to your project root:: + + project/ + app/ + templates/ + app/ + blog_index_page.html + models.py + +Class names are converted from camel case to underscores. For example, the template for model class ``BlogIndexPage`` would be assumed to be ``blog_index_page.html``. For more information, see the Django documentation for the `application directories template loader`_. + +.. _application directories template loader: https://docs.djangoproject.com/en/dev/ref/templates/api/ + + +Self +---- + +By default, the context passed to a model's template consists of two properties: ``self`` and ``request``. ``self`` is the model object being displayed. ``request`` is the normal Django request object. So, to include the title of a ``Page``, use ``{{ self.title }}``. ======================== Static files (css, js, images) @@ -104,14 +125,42 @@ The available ``method`` s are: To request the "original" version of an image, it is suggested you rely on the lack of upscalling support by requesting an image much larger than it's maximum dimensions. e.g to insert an image who's dimensions are uncertain/unknown, at it's maximum size, try: ``{% image self.image width-10000 %}``. This assumes the image is unlikely to be larger than 10000px wide. - Rich text (filter) ~~~~~~~~~~~~~~~~~~ +This filter is required for use with any ``RichTextField``. It will expand internal shorthand references to embeds and links made in the Wagtail editor into fully-baked HTML ready for display. **Note that the template tag loaded differs from the name of the filter.** + +.. code-block:: django + + {% load rich_text %} + ... + {{ body|richtext }} Internal links (tag) ~~~~~~~~~~~~~~~~~~~~ +**pageurl** + +Takes a ``Page``-derived object and returns its URL as relative (``/foo/bar/``) if it's within the same site as the current page, or absolute (``http://example.com/foo/bar/``) if not. + +.. code-block:: django + + {% load pageurl %} + ... + + +**slugurl** + +Takes a ``slug`` string and returns the URL for the ``Page``-derived object with that slug. Like ``pageurl``, will try to provide a relative link if possible, but will default to an absolute link if on a different site. + +.. code-block:: django + + {% load slugurl %} + ... + + + + Static files (tag) ~~~~~~~~~~~~~~ @@ -121,7 +170,15 @@ Misc ~~~~~~~~~~ + ======================== Wagtail User Bar ======================== +This tag provides a Wagtail icon and flyout menu on the top-right of a page for a logged-in user with editing capabilities, with the option of editing the current Page-derived object or adding a new sibling object. + +.. code-block:: django + + {% load wagtailuserbar %} + ... + {% wagtailuserbar %} diff --git a/docs/building_your_site/index.rst b/docs/building_your_site/index.rst index 0f122d8a6..a42c40099 100644 --- a/docs/building_your_site/index.rst +++ b/docs/building_your_site/index.rst @@ -1,492 +1,15 @@ Building your site ================== -<<<<<<< HEAD:docs/building_your_site.rst -Wagtail requires a little careful setup to define the types of content that you want to present through your website. The basic unit of content in Wagtail is the ``Page``, and all of your page-level content will inherit basic webpage-related properties from it. But for the most part, you will be defining content yourself, through the contruction of Django models using Wagtail's ``Page`` as a base. - -Wagtail organizes content created from your models in a tree, which can have any structure and combination of model objects in it. Wagtail doesn't prescribe ways to organize and interrelate your content, but here we've sketched out some strategies for organizing your models. - -The presentation of your content, the actual webpages, includes the normal use of the Django template system. We'll cover additional functionality that Wagtail provides at the template level later on. - -But first, we'll take a look at the ``Page`` class and model definitions. - - -The Page Class -~~~~~~~~~~~~~~ - -``Page`` uses Django's model interface, so you can include any field type and field options that Django allows. Wagtail provides some fields and editing handlers that simplify data entry in the Wagtail admin interface, so you may want to keep those in mind when deciding what properties to add to your models in addition to those already provided by ``Page``. - - -Built-in Properties of the Page Class -------------------------------------- - -Wagtail provides some properties in the ``Page`` class which are common to most webpages. Since you'll be subclassing ``Page``, you don't have to worry about implementing them. - -Public Properties -````````````````` - - ``title`` (string, required) - Human-readable title for the content - - ``slug`` (string, required) - Machine-readable URL component for this piece of content. The name of the page as it will appear in URLs e.g ``http://domain.com/blog/[my-slug]/`` - - ``seo_title`` (string) - Alternate SEO-crafted title which overrides the normal title for use in the ```` of a page - - ``search_description`` (string) - A SEO-crafted description of the content, used in both internal search indexing and for the meta description read by search engines - -The ``Page`` class actually has alot more to it, but these are probably the only built-in properties you'll need to worry about when creating templates for your models. - - -Anatomy of a Wagtail Model -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -So what does a Wagtail model definition look like? Here's a model representing a typical blog post: - -.. code-block:: python - - from django.db import models - - from wagtail.wagtailcore.models import Page - from wagtail.wagtailcore.fields import RichTextField - from wagtail.wagtailadmin.edit_handlers import FieldPanel - from wagtail.wagtailimages.edit_handlers import ImageChooserPanel - from wagtail.wagtailimages.models import Image - - class BlogPage(Page): - body = RichTextField() - date = models.DateField("Post date") - feed_image = models.ForeignKey( - 'wagtailimages.Image', - null=True, - blank=True, - on_delete=models.SET_NULL, - related_name='+' - ) - - BlogPage.content_panels = [ - FieldPanel('title', classname="full title"), - FieldPanel('date'), - FieldPanel('body', classname="full"), - ] - - BlogPage.promote_panels = [ - FieldPanel('slug'), - FieldPanel('seo_title'), - FieldPanel('show_in_menus'), - FieldPanel('search_description'), - ImageChooserPanel('feed_image'), - ] - -To keep track of your ``Page``-derived models, it might be helpful to include "Page" as the last part of your classname. ``BlogPage`` defines three properties: ``body``, ``date``, and ``feed_image``. These are a mix of basic Django models (``DateField``), Wagtail fields (``RichTextField``), and a pointer to a Wagtail model (``Image``). - -Next, the ``content_panels`` and ``promote_panels`` lists define the capabilities and layout of the Wagtail admin page edit interface. The lists are filled with "panels" and "choosers", which will provide a fine-grain interface for inputting the model's content. The ``ImageChooserPanel``, for instance, lets one browse the image library, upload new images, and input image metadata. The ``RichTextField`` is the basic field for creating web-ready website rich text, including text formatting and embedded media like images and video. The Wagtail admin offers other choices for fields, Panels, and Choosers, with the option of creating your own to precisely fit your content without workarounds or other compromises. - -Your models may be even more complex, with methods overriding the built-in functionality of the ``Page`` to achieve webdev magic. Or, you can keep your models simple and let Wagtail's built-in functionality do the work. - -Now that we have a basic idea of how our content is defined, lets look at relationships between pieces of content. - - -Introduction to Trees -~~~~~~~~~~~~~~~~~~~~~ - -If you're unfamiliar with trees as an abstract data type, you might want to `review the concepts involved. `_ - -As a web developer, though, you probably already have a good understanding of trees as filesystem directories or paths. Wagtail pages can create the same structure, as each page in the tree has its own URL path, like so:: - - / - people/ - nien-nunb/ - laura-roslin/ - events/ - captain-picard-day/ - winter-wrap-up/ - -The Wagtail admin interface uses the tree to organize content for editing, letting you navigate up and down levels in the tree through its Explorer menu. This method of organization is a good place to start in thinking about your own Wagtail models. - - -Nodes and Leaves ----------------- - -It might be handy to think of the ``Page``-derived models you want to create as being one of two node types: parents and leaves. Wagtail isn't prescriptive in this approach, but it's a good place to start if you're not experienced in structuring your own content types. - - -Nodes -````` -Parent nodes on the Wagtail tree probably want to organize and display a browsable index of their descendents. A blog, for instance, needs a way to show a list of individual posts. - -A Parent node could provide its own function returning its descendant objects. - -.. code-block:: python - - class EventPageIndex(Page): - ... - def events(self): - # Get list of event pages that are descendants of this page - events = EventPage.objects.filter( - live=True, - path__startswith=self.path - ) - return events - -This example makes sure to limit the returned objects to pieces of content which make sense, specifically ones which have been published through Wagtail's admin interface (``live=True``) and are descendants of this node. Wagtail will allow the "illogical" placement of child nodes under a parent, so it's necessary for a parent model to index only those children which make sense. - - -Leaves -`````` -Leaves are the pieces of content itself, a page which is consumable, and might just consist of a bunch of properties. A blog page leaf might have some body text and an image. A person page leaf might have a photo, a name, and an address. - -It might be helpful for a leaf to provide a way to back up along the tree to a parent, such as in the case of breadcrumbs navigation. The tree might also be deep enough that a leaf's parent won't be included in general site navigation. - -The model for the leaf could provide a function that traverses the tree in the opposite direction and returns an appropriate ancestor: - -.. code-block:: python - - class BlogPage(Page): - ... - def blog_index(self): - # Find blog index in ancestors - for ancestor in reversed(self.get_ancestors()): - if isinstance(ancestor.specific, BlogIndexPage): - return ancestor - - # No ancestors are blog indexes, just return first blog index in database - return BlogIndexPage.objects.first() - -Since Wagtail doesn't limit what Page-derived classes can be assigned as parents and children, the reverse tree traversal needs to accommodate cases which might not be expected, such as the lack of a "logical" parent to a leaf. - - -Other Relationships -``````````````````` -Your ``Page``-derived models might have other interrelationships which extend the basic Wagtail tree or depart from it entirely. You could provide functions to navigate between siblings, such as a "Next Post" link on a blog page (``post->post->post``). It might make sense for subtrees to interrelate, such as in a discussion forum (``forum->post->replies``) Skipping across the hierarchy might make sense, too, as all objects of a certain model class might interrelate regardless of their ancestors (``events = EventPage.objects.all``). Since there's no restriction on the combination of model classes that can be used at any point in the tree, and it's largely up to the models to define their interrelations, the possibilities are really endless. - - -Anatomy of a Wagtail Request -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -For going beyond the basics of model definition and interrelation, it might help to know how Wagtail handles requests and constructs responses. In short, it goes something like: - - #. Django gets a request and routes through Wagtail's URL dispatcher definitions - #. Starting from the root content piece, Wagtail traverses the page tree, letting the model for each piece of content along the path decide how to ``route()`` the next step in the path. - #. A model class decides that routing is done and it's now time to ``serve()`` content. - #. The model constructs a context, finds a template to pass it to, and renders the content. - #. The templates are rendered and the response object is sent back to the requester. - -You can apply custom behavior to this process by overriding the ``route()`` and ``serve()`` methods of the ``Page`` class in your own models. - - -Model Recipes -~~~~~~~~~~~~~ - -Overriding the serve() Method ------------------------------ - -Wagtail defaults to serving ``Page``-derived models by passing ``self`` to a Django HTML template matching the model's name, but suppose you wanted to serve something other than HTML? You can override the ``serve()`` method provided by the ``Page`` class and handle the Django request and response more directly. - -Consider this example from the Wagtail demo site's ``models.py``, which serves an ``EventPage`` object as an iCal file if the ``format`` variable is set in the request: - -.. code-block:: python - - class EventPage(Page): - ... - def serve(self, request): - if "format" in request.GET: - if request.GET['format'] == 'ical': - # Export to ical format - response = HttpResponse( - export_event(self, 'ical'), - content_type='text/calendar', - ) - response['Content-Disposition'] = 'attachment; filename=' + self.slug + '.ics' - return response - else: - # Unrecognised format error - message = 'Could not export event\n\nUnrecognised format: ' + request.GET['format'] - return HttpResponse(message, content_type='text/plain') - else: - # Display event page as usual - return super(EventPage, self).serve(request) - -``serve()`` takes a Django request object and returns a Django response object. Wagtail returns a ``TemplateResponse`` object with the template and context which it generates, which allows middleware to function as intended, so keep in mind that a simpler response object like a ``HttpResponse`` will not receive these benefits. - -With this strategy, you could use Django or Python utilities to render your model in JSON or XML or any other format you'd like. - - -Adding Endpoints with Custom route() Methods --------------------------------------------- - -Wagtail routes requests by iterating over the path components (separated with a forward slash ``/``), finding matching objects based on their slug, and delegating further routing to that object's model class. The Wagtail source is very instructive in figuring out what's happening. This is the default ``route()`` method of the ``Page`` class: - -.. code-block:: python - - class Page(...): - - ... - - def route(self, request, path_components): - if path_components: - # request is for a child of this page - child_slug = path_components[0] - remaining_components = path_components[1:] - - # find a matching child or 404 - try: - subpage = self.get_children().get(slug=child_slug) - except Page.DoesNotExist: - raise Http404 - - # delegate further routing - return subpage.specific.route(request, remaining_components) - - else: - # request is for this very page - if self.live: - # use the serve() method to render the request if the page is published - return self.serve(request) - else: - # the page matches the request, but isn't published, so 404 - raise Http404 - -The contract is pretty simple. ``route()`` takes the current object (``self``), the ``request`` object, and a list of the remaining ``path_components`` from the request URL. It either continues delegating routing by calling ``route()`` again on one of its children in the Wagtail tree, or ends the routing process by serving something -- either normally through the ``self.serve()`` method or by raising a 404 error. - -By overriding the ``route()`` method, we could create custom endpoints for each object in the Wagtail tree. One use case might be using an alternate template when encountering the ``print/`` endpoint in the path. Another might be a REST API which interacts with the current object. Just to see what's involved, lets make a simple model which prints out all of its child path components. - -First, ``models.py``: - -.. code-block:: python - - from django.shortcuts import render - - ... - - class Echoer(Page): - - def route(self, request, path_components): - if path_components: - return render(request, self.template, { - 'self': self, - 'echo': ' '.join(path_components), - }) - else: - if self.live: - return self.serve(request) - else: - raise Http404 - - Echoer.content_panels = [ - FieldPanel('title', classname="full title"), - ] - - Echoer.promote_panels = [ - MultiFieldPanel(COMMON_PANELS, "Common page configuration"), - ] - -This model, ``Echoer``, doesn't define any properties, but does subclass ``Page`` so objects will be able to have a custom title and slug. The template just has to display our ``{{ echo }}`` property. We're skipping the ``serve()`` method entirely, but you could include your render code there to stay consistent with Wagtail's conventions. - -Now, once creating a new ``Echoer`` page in the Wagtail admin titled "Echo Base," requests such as:: - - http://127.0.0.1:8000/echo-base/tauntaun/kennel/bed/and/breakfast/ - -Will return:: - - tauntaun kennel bed and breakfast - -Lovely, huh? (We know.) - - - -Tagging -------- - -Wagtail provides tagging capability through the combination of two django modules, ``taggit`` and ``modelcluster``. ``taggit`` provides a model for tags which is extended by ``modelcluster``, which in turn provides some magical database abstraction which makes drafts and revisions possible in Wagtail. It's a tricky recipe, but the net effect is a many-to-many relationship between your model and a tag class reserved for your model. - -Using an example from the Wagtail demo site, here's what the tag model and the relationship field looks like in ``models.py``: - -.. code-block:: python - - from modelcluster.fields import ParentalKey - from modelcluster.tags import ClusterTaggableManager - from taggit.models import Tag, TaggedItemBase - ... - class BlogPageTag(TaggedItemBase): - content_object = ParentalKey('demo.BlogPage', related_name='tagged_items') - ... - class BlogPage(Page): - ... - tags = ClusterTaggableManager(through=BlogPageTag, blank=True) - - BlogPage.promote_panels = [ - ... - FieldPanel('tags'), - ] - -Wagtail's admin provides a nice interface for inputting tags into your content, with typeahead tag completion and friendly tag icons. - -Now that we have the many-to-many tag relationship in place, we can fit in a way to render both sides of the relation. Here's more of the Wagtail demo site ``models.py``, where the index model for ``BlogPage`` is extended with logic for filtering the index by tag: - -.. code-block:: python - - class BlogIndexPage(Page): - ... - def serve(self, request): - # Get blogs - blogs = self.blogs - - # Filter by tag - tag = request.GET.get('tag') - if tag: - blogs = blogs.filter(tags__name=tag) - - return render(request, self.template, { - 'self': self, - 'blogs': blogs, - }) - -Here, ``blogs.filter(tags__name=tag)`` invokes a reverse Django queryset filter on the ``BlogPageTag`` model to optionally limit the ``BlogPage`` objects sent to the template for rendering. Now, lets render both sides of the relation by showing the tags associated with an object and a way of showing all of the objects associated with each tag. This could be added to the ``blog_page.html`` template: - -.. code-block:: django - - {% for tag in self.tags.all %} - {{ tag }} - {% endfor %} - -Iterating through ``self.tags.all`` will display each tag associated with ``self``, while the link(s) back to the index make use of the filter option added to the ``BlogIndexPage`` model. A Django query could also use the ``tagged_items`` related name field to get ``BlogPage`` objects associated with a tag. - -This is just one possible way of creating a taxonomy for Wagtail objects. With all of the components for a taxonomy available through Wagtail, you should be able to fulfill even the most exotic taxonomic schemes. - - - - - - - - - - - -Templates -~~~~~~~~~ - -Location --------- - -For each of your ``Page``-derived models, Wagtail will look for a template in the following location, relative to your project root:: - - project/ - app/ - templates/ - app/ - blog_index_page.html - models.py - -Class names are converted from camel case to underscores. For example, the template for model class ``BlogIndexPage`` would be assumed to be ``blog_index_page.html``. For more information, see the Django documentation for the `application directories template loader`_. - -.. _application directories template loader: https://docs.djangoproject.com/en/dev/ref/templates/api/ - - -Self ----- - -By default, the context passed to a model's template consists of two properties: ``self`` and ``request``. ``self`` is the model object being displayed. ``request`` is the normal Django request object. - - -Template Tags -------------- - - **pageurl** - - Takes a ``Page``-derived object and returns its URL as relative (``/foo/bar/``) if it's within the same site as the current page, or absolute (``http://example.com/foo/bar/``) if not. - - .. code-block:: django - - {% load pageurl %} - ... - - - **slugurl** - - Takes a ``slug`` string and returns the URL for the ``Page``-derived object with that slug. Like ``pageurl``, will try to provide a relative link if possible, but will default to an absolute link if on a different site. - - - .. code-block:: django - - {% load slugurl %} - ... - - - **wagtailuserbar** - - This tag provides a Wagtail icon and flyout menu on the top-right of a page for a logged-in user with editing capabilities, with the option of editing the current Page-derived object or adding a new sibling object. - - .. code-block:: django - - {% load wagtailuserbar %} - ... - {% wagtailuserbar %} - - **image** - - This template tag provides a way to process an image with a method and dimensions. - - .. code-block:: django - - {% load image_tags %} - ... - {% image self.photo max-320x200 %} - or - {% image self.photo max-320x200 as img %} - - 'max': 'resize_to_max', - 'min': 'resize_to_min', - 'width': 'resize_to_width', - 'height': 'resize_to_height', - 'fill': 'resize_to_fill', - - -Template Filters ----------------- - - **rich_text** - - This filter is required for use with any ``RichTextField``. It will expand internal shorthand references to embeds and links made in the Wagtail editor into fully-baked HTML ready for display. **Note that the template tag loaded differs from the name of the filter.** - - .. code-block:: django - - {% load rich_text %} - ... - {{ body|richtext }} - - - -Site -~~~~ - -Django's built-in admin interface provides the way to map a "site" (hostname or domain) to any node in the wagtail tree, using that node as the site's root. - -Access this by going to ``/django-admin/`` and then "Home › Wagtailcore › Sites." To try out a development site, add a single site with the hostname ``localhost`` at port ``8000`` and map it to one of the pieces of content you have created. - -Wagtail's developers plan to move the site settings into the Wagtail admin interface. - - - -Example Site -~~~~~~~~~~~~ -======= .. note:: - Documentation currently incomplete and in draft status ->>>>>>> cde047f4850770ae0ffd2fcbf0580336bb6cf8ac:docs/building_your_site/index.rst + Documentation currently incomplete and in draft status Serafeim Papastefanos has written a comprehensive tutorial on creating a site from scratch in Wagtail; for the time being, this is our recommended resource: `spapas.github.io/2014/02/13/wagtail-tutorial/ `_ -<<<<<<< HEAD:docs/building_your_site.rst -======= .. toctree:: - :maxdepth: 3 + :maxdepth: 3 - djangodevelopers - frontenddevelopers ->>>>>>> cde047f4850770ae0ffd2fcbf0580336bb6cf8ac:docs/building_your_site/index.rst + djangodevelopers + frontenddevelopers diff --git a/docs/editing_api.rst b/docs/editing_api.rst index 8fcb0b715..2985a1229 100644 --- a/docs/editing_api.rst +++ b/docs/editing_api.rst @@ -2,6 +2,10 @@ Editing API =========== +.. note:: + This documentation is currently being written. + + Wagtail provides a highly-customizable editing interface consisting of several components: * **Fields** — built-in content types to augment the basic types provided by Django. @@ -93,6 +97,8 @@ If you're interested in extending the capabilities of the Wagtail editor, See :r Images ------ +.. code-block:: python + from wagtail.wagtailimages.models import Image feed_image = models.ForeignKey( @@ -107,6 +113,8 @@ Images Documents --------- +.. code-block:: python + from wagtail.wagtaildocs.models import Document link_document = models.ForeignKey( @@ -120,6 +128,8 @@ Documents Pages and Page-derived Models ----------------------------- +.. code-block:: python + from wagtail.wagtailcore.models import Page page = models.ForeignKey( @@ -137,6 +147,8 @@ Snippets (and Basic Django Models?) Snippets are not not subclasses, so you must include the model class directly. A chooser is provided which takes the snippet class. +.. code-block:: python + advert = models.ForeignKey( 'demo.Advert', related_name='+' diff --git a/docs/index.rst b/docs/index.rst index f64eec0b9..abbb7fdbe 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -9,14 +9,15 @@ It supports Django 1.6.2+ on Python 2.6 and 2.7. Django 1.7 and Python 3 support :maxdepth: 3 gettingstarted + building_your_site/index editing_api snippets - building_your_site/index wagtail_search + form_builder + model_recipes advanced_topics deploying performance - form_builder static_site_generation contributing support diff --git a/docs/model_recipes.rst b/docs/model_recipes.rst new file mode 100644 index 000000000..db88daf7c --- /dev/null +++ b/docs/model_recipes.rst @@ -0,0 +1,176 @@ + +Model Recipes +============= + +Overriding the serve() Method +----------------------------- + +Wagtail defaults to serving ``Page``-derived models by passing ``self`` to a Django HTML template matching the model's name, but suppose you wanted to serve something other than HTML? You can override the ``serve()`` method provided by the ``Page`` class and handle the Django request and response more directly. + +Consider this example from the Wagtail demo site's ``models.py``, which serves an ``EventPage`` object as an iCal file if the ``format`` variable is set in the request: + +.. code-block:: python + + class EventPage(Page): + ... + def serve(self, request): + if "format" in request.GET: + if request.GET['format'] == 'ical': + # Export to ical format + response = HttpResponse( + export_event(self, 'ical'), + content_type='text/calendar', + ) + response['Content-Disposition'] = 'attachment; filename=' + self.slug + '.ics' + return response + else: + # Unrecognised format error + message = 'Could not export event\n\nUnrecognised format: ' + request.GET['format'] + return HttpResponse(message, content_type='text/plain') + else: + # Display event page as usual + return super(EventPage, self).serve(request) + +``serve()`` takes a Django request object and returns a Django response object. Wagtail returns a ``TemplateResponse`` object with the template and context which it generates, which allows middleware to function as intended, so keep in mind that a simpler response object like a ``HttpResponse`` will not receive these benefits. + +With this strategy, you could use Django or Python utilities to render your model in JSON or XML or any other format you'd like. + + +Adding Endpoints with Custom route() Methods +-------------------------------------------- + +Wagtail routes requests by iterating over the path components (separated with a forward slash ``/``), finding matching objects based on their slug, and delegating further routing to that object's model class. The Wagtail source is very instructive in figuring out what's happening. This is the default ``route()`` method of the ``Page`` class: + +.. code-block:: python + + class Page(...): + + ... + + def route(self, request, path_components): + if path_components: + # request is for a child of this page + child_slug = path_components[0] + remaining_components = path_components[1:] + + # find a matching child or 404 + try: + subpage = self.get_children().get(slug=child_slug) + except Page.DoesNotExist: + raise Http404 + + # delegate further routing + return subpage.specific.route(request, remaining_components) + + else: + # request is for this very page + if self.live: + # use the serve() method to render the request if the page is published + return self.serve(request) + else: + # the page matches the request, but isn't published, so 404 + raise Http404 + +The contract is pretty simple. ``route()`` takes the current object (``self``), the ``request`` object, and a list of the remaining ``path_components`` from the request URL. It either continues delegating routing by calling ``route()`` again on one of its children in the Wagtail tree, or ends the routing process by serving something -- either normally through the ``self.serve()`` method or by raising a 404 error. + +By overriding the ``route()`` method, we could create custom endpoints for each object in the Wagtail tree. One use case might be using an alternate template when encountering the ``print/`` endpoint in the path. Another might be a REST API which interacts with the current object. Just to see what's involved, lets make a simple model which prints out all of its child path components. + +First, ``models.py``: + +.. code-block:: python + + from django.shortcuts import render + + ... + + class Echoer(Page): + + def route(self, request, path_components): + if path_components: + return render(request, self.template, { + 'self': self, + 'echo': ' '.join(path_components), + }) + else: + if self.live: + return self.serve(request) + else: + raise Http404 + + Echoer.content_panels = [ + FieldPanel('title', classname="full title"), + ] + + Echoer.promote_panels = [ + MultiFieldPanel(COMMON_PANELS, "Common page configuration"), + ] + +This model, ``Echoer``, doesn't define any properties, but does subclass ``Page`` so objects will be able to have a custom title and slug. The template just has to display our ``{{ echo }}`` property. We're skipping the ``serve()`` method entirely, but you could include your render code there to stay consistent with Wagtail's conventions. + +Now, once creating a new ``Echoer`` page in the Wagtail admin titled "Echo Base," requests such as:: + + http://127.0.0.1:8000/echo-base/tauntaun/kennel/bed/and/breakfast/ + +Will return:: + + tauntaun kennel bed and breakfast + + +Tagging +------- + +Wagtail provides tagging capability through the combination of two django modules, ``taggit`` and ``modelcluster``. ``taggit`` provides a model for tags which is extended by ``modelcluster``, which in turn provides some magical database abstraction which makes drafts and revisions possible in Wagtail. It's a tricky recipe, but the net effect is a many-to-many relationship between your model and a tag class reserved for your model. + +Using an example from the Wagtail demo site, here's what the tag model and the relationship field looks like in ``models.py``: + +.. code-block:: python + + from modelcluster.fields import ParentalKey + from modelcluster.tags import ClusterTaggableManager + from taggit.models import Tag, TaggedItemBase + ... + class BlogPageTag(TaggedItemBase): + content_object = ParentalKey('demo.BlogPage', related_name='tagged_items') + ... + class BlogPage(Page): + ... + tags = ClusterTaggableManager(through=BlogPageTag, blank=True) + + BlogPage.promote_panels = [ + ... + FieldPanel('tags'), + ] + +Wagtail's admin provides a nice interface for inputting tags into your content, with typeahead tag completion and friendly tag icons. + +Now that we have the many-to-many tag relationship in place, we can fit in a way to render both sides of the relation. Here's more of the Wagtail demo site ``models.py``, where the index model for ``BlogPage`` is extended with logic for filtering the index by tag: + +.. code-block:: python + + class BlogIndexPage(Page): + ... + def serve(self, request): + # Get blogs + blogs = self.blogs + + # Filter by tag + tag = request.GET.get('tag') + if tag: + blogs = blogs.filter(tags__name=tag) + + return render(request, self.template, { + 'self': self, + 'blogs': blogs, + }) + +Here, ``blogs.filter(tags__name=tag)`` invokes a reverse Django queryset filter on the ``BlogPageTag`` model to optionally limit the ``BlogPage`` objects sent to the template for rendering. Now, lets render both sides of the relation by showing the tags associated with an object and a way of showing all of the objects associated with each tag. This could be added to the ``blog_page.html`` template: + +.. code-block:: django + + {% for tag in self.tags.all %} + {{ tag }} + {% endfor %} + +Iterating through ``self.tags.all`` will display each tag associated with ``self``, while the link(s) back to the index make use of the filter option added to the ``BlogIndexPage`` model. A Django query could also use the ``tagged_items`` related name field to get ``BlogPage`` objects associated with a tag. + +This is just one possible way of creating a taxonomy for Wagtail objects. With all of the components for a taxonomy available through Wagtail, you should be able to fulfill even the most exotic taxonomic schemes. From 1d6eee6b36cdaca80d628bf502f616ea8de202f4 Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Thu, 22 May 2014 19:50:44 -0400 Subject: [PATCH 48/57] fixed pygments thing --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 4112e3753..11517ada2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -93,7 +93,7 @@ exclude_patterns = ['_build'] #show_authors = False # The name of the Pygments (syntax highlighting) style to use. -#pygments_style = 'sphinx' +pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] From 40d9aff789a5741406b60c934d8b59ba5ead172a Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Thu, 22 May 2014 19:53:49 -0400 Subject: [PATCH 49/57] didnt intend to edit that file --- docs/building_your_site/index.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/building_your_site/index.rst b/docs/building_your_site/index.rst index a42c40099..fb336e18b 100644 --- a/docs/building_your_site/index.rst +++ b/docs/building_your_site/index.rst @@ -2,14 +2,14 @@ Building your site ================== .. note:: - Documentation currently incomplete and in draft status + Documentation currently incomplete and in draft status Serafeim Papastefanos has written a comprehensive tutorial on creating a site from scratch in Wagtail; for the time being, this is our recommended resource: `spapas.github.io/2014/02/13/wagtail-tutorial/ `_ .. toctree:: - :maxdepth: 3 + :maxdepth: 3 - djangodevelopers - frontenddevelopers + djangodevelopers + frontenddevelopers From 9d45d3a4a29c0ee7a94456de96439a6f7ce9f0f6 Mon Sep 17 00:00:00 2001 From: Dave Cranwell Date: Fri, 23 May 2014 10:22:32 +0100 Subject: [PATCH 50/57] Update README.rst --- README.rst | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 9a1961b32..a102c0f51 100644 --- a/README.rst +++ b/README.rst @@ -26,9 +26,7 @@ Wagtail is a Django content management system built originally for the `Royal Co * Fast out of the box. `Varnish `_-friendly if you need it * Tests! But not enough; we're working hard to improve this -It supports Django 1.6.2+ on Python 2.6 and 2.7. Django 1.7 and Python 3 support are in progress. - -Find out more at `wagtail.io `_. Documentation is at `wagtail.readthedocs.org `_. +Find out more at `wagtail.io `_. Got a question? Ask it on our `Google Group `_. @@ -38,6 +36,15 @@ Getting started * See the `Getting Started `_ docs for installation (with the demo app) on a fresh Debian/Ubuntu box with production-ready dependencies, on OS X and on a Vagrant box. * `Serafeim Papastefanos `_ has written a `tutorial `_ with all the steps to build a simple Wagtail site from scratch. +Documentation +~~~~~~~~~~~~~ +`wagtail.readthedocs.org `_. + +Compatibility +~~~~~~~~~~~~~ +Wagtao; supports Django 1.6.2+ on Python 2.6 and 2.7. Django 1.7 and Python 3 support are in progress. + Contributing ~~~~~~~~~~~~ If you're a Python or Django developer, fork the repo and get stuck in! Send us a useful pull request and we'll post you a `t-shirt `_. Our immediate priorities are better docs, more tests, internationalisation and localisation. + From 2edb0695031ffae79705834b23933f6533505aad Mon Sep 17 00:00:00 2001 From: Dave Cranwell Date: Fri, 23 May 2014 10:22:49 +0100 Subject: [PATCH 51/57] Update README.rst --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index a102c0f51..8e7b174b7 100644 --- a/README.rst +++ b/README.rst @@ -42,7 +42,7 @@ Documentation Compatibility ~~~~~~~~~~~~~ -Wagtao; supports Django 1.6.2+ on Python 2.6 and 2.7. Django 1.7 and Python 3 support are in progress. +Wagtail supports Django 1.6.2+ on Python 2.6 and 2.7. Django 1.7 and Python 3 support are in progress. Contributing ~~~~~~~~~~~~ From b5a0e6731b58a6e2be0c26a79c73a1df5580b97c Mon Sep 17 00:00:00 2001 From: Dave Cranwell Date: Fri, 23 May 2014 11:49:39 +0100 Subject: [PATCH 52/57] Update README.rst --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 8e7b174b7..eddbb85fc 100644 --- a/README.rst +++ b/README.rst @@ -38,7 +38,7 @@ Getting started Documentation ~~~~~~~~~~~~~ -`wagtail.readthedocs.org `_. +Available at `wagtail.readthedocs.org `_. and always being updated. Compatibility ~~~~~~~~~~~~~ From 992ef2eec7d4e39e1a1a04e2aa262a0fa1bad712 Mon Sep 17 00:00:00 2001 From: Neal Todd Date: Fri, 23 May 2014 15:33:21 +0100 Subject: [PATCH 53/57] Typo fix --- docs/gettingstarted.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/gettingstarted.rst b/docs/gettingstarted.rst index a46ea9664..458de387b 100644 --- a/docs/gettingstarted.rst +++ b/docs/gettingstarted.rst @@ -166,4 +166,4 @@ Once you've experimented with the demo app and are ready to build your pages via COMMIT; EOF rm -r demo media/images/* media/original_images/* - perl -pi -e"s/('demo',|WAGTAILSEARCH_RESULTS_TEMPLATE)/#\1/" $PROJECT/settingsbase.py + perl -pi -e"s/('demo',|WAGTAILSEARCH_RESULTS_TEMPLATE)/#\1/" $PROJECT/settings/base.py From 94af650c8380688e48af99f3467fb1dac7ae0dea Mon Sep 17 00:00:00 2001 From: Jeffrey Hearn Date: Fri, 23 May 2014 23:03:07 -0400 Subject: [PATCH 54/57] Spellchecked, cleaned, and Edit API section expanded Added to edit api, fixed queryset example code, stubbed out Page ref Some cleanup of the edit api doc Some cleanup of the frontend doc Added to edit api docs Added to edit api docs --- docs/building_your_site/djangodevelopers.rst | 145 +++++++++-- .../building_your_site/frontenddevelopers.rst | 16 +- docs/editing_api.rst | 228 +++++++++++++----- docs/model_recipes.rst | 23 ++ docs/snippets.rst | 5 +- docs/wagtail_search.rst | 6 +- 6 files changed, 333 insertions(+), 90 deletions(-) diff --git a/docs/building_your_site/djangodevelopers.rst b/docs/building_your_site/djangodevelopers.rst index 49f80c371..5632a419b 100644 --- a/docs/building_your_site/djangodevelopers.rst +++ b/docs/building_your_site/djangodevelopers.rst @@ -4,7 +4,7 @@ For Django developers .. note:: This documentation is currently being written. -Wagtail requires a little careful setup to define the types of content that you want to present through your website. The basic unit of content in Wagtail is the ``Page``, and all of your page-level content will inherit basic webpage-related properties from it. But for the most part, you will be defining content yourself, through the contruction of Django models using Wagtail's ``Page`` as a base. +Wagtail requires a little careful setup to define the types of content that you want to present through your website. The basic unit of content in Wagtail is the ``Page``, and all of your page-level content will inherit basic webpage-related properties from it. But for the most part, you will be defining content yourself, through the construction of Django models using Wagtail's ``Page`` as a base. Wagtail organizes content created from your models in a tree, which can have any structure and combination of model objects in it. Wagtail doesn't prescribe ways to organize and interrelate your content, but here we've sketched out some strategies for organizing your models. @@ -82,7 +82,7 @@ So what does a Wagtail model definition look like? Here's a model representing a ImageChooserPanel('feed_image'), ] -To keep track of your ``Page``-derived models, it might be helpful to include "Page" as the last part of your classname. ``BlogPage`` defines three properties: ``body``, ``date``, and ``feed_image``. These are a mix of basic Django models (``DateField``), Wagtail fields (``RichTextField``), and a pointer to a Wagtail model (``Image``). +To keep track of your ``Page``-derived models, it might be helpful to include "Page" as the last part of your class name. ``BlogPage`` defines three properties: ``body``, ``date``, and ``feed_image``. These are a mix of basic Django models (``DateField``), Wagtail fields (``RichTextField``), and a pointer to a Wagtail model (``Image``). Next, the ``content_panels`` and ``promote_panels`` lists define the capabilities and layout of the Wagtail admin page edit interface. The lists are filled with "panels" and "choosers", which will provide a fine-grain interface for inputting the model's content. The ``ImageChooserPanel``, for instance, lets one browse the image library, upload new images, and input image metadata. The ``RichTextField`` is the basic field for creating web-ready website rich text, including text formatting and embedded media like images and video. The Wagtail admin offers other choices for fields, Panels, and Choosers, with the option of creating your own to precisely fit your content without workarounds or other compromises. @@ -117,23 +117,28 @@ It might be handy to think of the ``Page``-derived models you want to create as Nodes ````` -Parent nodes on the Wagtail tree probably want to organize and display a browsable index of their descendents. A blog, for instance, needs a way to show a list of individual posts. +Parent nodes on the Wagtail tree probably want to organize and display a browse-able index of their descendants. A blog, for instance, needs a way to show a list of individual posts. A Parent node could provide its own function returning its descendant objects. .. code-block:: python class EventPageIndex(Page): - ... + # ... def events(self): - # Get list of event pages that are descendants of this page - events = EventPage.objects.filter( - live=True, - path__startswith=self.path - ) + # Get list of live event pages that are descendants of this page + events = EventPage.objects.live().descendant_of(self) + + # Filter events list to get ones that are either + # running now or start in the future + events = events.filter(date_from__gte=date.today()) + + # Order by date + events = events.order_by('date_from') + return events -This example makes sure to limit the returned objects to pieces of content which make sense, specifically ones which have been published through Wagtail's admin interface (``live=True``) and are descendants of this node. Wagtail will allow the "illogical" placement of child nodes under a parent, so it's necessary for a parent model to index only those children which make sense. +This example makes sure to limit the returned objects to pieces of content which make sense, specifically ones which have been published through Wagtail's admin interface (``live()``) and are children of this node (``descendant_of(self)``). By setting a ``subpage_types`` class property in your model, you can specify which models are allowed to be set as children, but Wagtail will allow any ``Page``-derived model by default. Regardless, it's smart for a parent model to provide an index filtered to make sense. Leaves @@ -146,23 +151,18 @@ The model for the leaf could provide a function that traverses the tree in the o .. code-block:: python - class BlogPage(Page): - ... - def blog_index(self): - # Find blog index in ancestors - for ancestor in reversed(self.get_ancestors()): - if isinstance(ancestor.specific, BlogIndexPage): - return ancestor + class EventPage(Page): + # ... + def event_index(self): + # Find closest ancestor which is an event index + return self.get_ancestors().type(EventIndexPage).last() - # No ancestors are blog indexes, just return first blog index in database - return BlogIndexPage.objects.first() - -Since Wagtail doesn't limit what Page-derived classes can be assigned as parents and children, the reverse tree traversal needs to accommodate cases which might not be expected, such as the lack of a "logical" parent to a leaf. +If defined, ``subpage_types`` will also limit the parent models allowed to contain a leaf. If not, Wagtail will allow any combination of parents and leafs to be associated in the Wagtail tree. Like with index pages, it's a good idea to make sure that the index is actually of the expected model to contain the leaf. Other Relationships ``````````````````` -Your ``Page``-derived models might have other interrelationships which extend the basic Wagtail tree or depart from it entirely. You could provide functions to navigate between siblings, such as a "Next Post" link on a blog page (``post->post->post``). It might make sense for subtrees to interrelate, such as in a discussion forum (``forum->post->replies``) Skipping across the hierarchy might make sense, too, as all objects of a certain model class might interrelate regardless of their ancestors (``events = EventPage.objects.all``). Since there's no restriction on the combination of model classes that can be used at any point in the tree, and it's largely up to the models to define their interrelations, the possibilities are really endless. +Your ``Page``-derived models might have other interrelationships which extend the basic Wagtail tree or depart from it entirely. You could provide functions to navigate between siblings, such as a "Next Post" link on a blog page (``post->post->post``). It might make sense for subtrees to interrelate, such as in a discussion forum (``forum->post->replies``) Skipping across the hierarchy might make sense, too, as all objects of a certain model class might interrelate regardless of their ancestors (``events = EventPage.objects.all``). It's largely up to the models to define their interrelations, the possibilities are really endless. Anatomy of a Wagtail Request @@ -173,10 +173,105 @@ For going beyond the basics of model definition and interrelation, it might help #. Django gets a request and routes through Wagtail's URL dispatcher definitions #. Starting from the root content piece, Wagtail traverses the page tree, letting the model for each piece of content along the path decide how to ``route()`` the next step in the path. #. A model class decides that routing is done and it's now time to ``serve()`` content. - #. The model constructs a context, finds a template to pass it to, and renders the content. - #. The templates are rendered and the response object is sent back to the requester. + #. ``serve()`` constructs a context using ``get_context()`` + #. ``serve()`` finds a template to pass it to using ``get_template()`` + #. A response object is returned by ``serve()`` and Django responds to the requester. + +You can apply custom behavior to this process by overriding ``Page`` class methods such as ``route()`` and ``serve()`` in your own models. For examples, see :ref:`model_recipes`. + + +Page Properties and Methods Reference +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In addition to the model fields provided, ``Page`` has many properties and methods that you may wish to reference, use, or override in creating your own models. Those listed here are relatively straightforward to use, but consult the Wagtail source code for a full view of what's possible. + +Properties: + +specific +url +full_url +relative_url +has_unpublished_changes +status_string +subpage_types +indexed_fields + + +Methods: + +route +serve +get_context +get_template +is_navigable +get_other_siblings +get_ancestors +get_descendants +get_siblings +search +get_page_modes +show_as_mode + + + + + +Page Queryset Methods +~~~~~~~~~~~~~~~~~~~~~ + +The ``Page`` class uses a custom Django model manager which provides these methods for structuring queries on ``Page`` objects. + +get_query_set() + return PageQuerySet(self.model).order_by('path') + +live(self): + return self.get_query_set().live() + +not_live(self): + return self.get_query_set().not_live() + +page(self, other): + return self.get_query_set().page(other) + +not_page(self, other): + return self.get_query_set().not_page(other) + +descendant_of(self, other, inclusive=False): + return self.get_query_set().descendant_of(other, inclusive) + +not_descendant_of(self, other, inclusive=False): + return self.get_query_set().not_descendant_of(other, inclusive) + +child_of(self, other): + return self.get_query_set().child_of(other) + +not_child_of(self, other): + return self.get_query_set().not_child_of(other) + +ancestor_of(self, other, inclusive=False): + return self.get_query_set().ancestor_of(other, inclusive) + +not_ancestor_of(self, other, inclusive=False): + return self.get_query_set().not_ancestor_of(other, inclusive) + +parent_of(self, other): + return self.get_query_set().parent_of(other) + +not_parent_of(self, other): + return self.get_query_set().not_parent_of(other) + +sibling_of(self, other, inclusive=False): + return self.get_query_set().sibling_of(other, inclusive) + +not_sibling_of(self, other, inclusive=False): + return self.get_query_set().not_sibling_of(other, inclusive) + +type(self, model): + return self.get_query_set().type(model) + +not_type(self, model): + return self.get_query_set().not_type(model) -You can apply custom behavior to this process by overriding the ``route()`` and ``serve()`` methods of the ``Page`` class in your own models. Site diff --git a/docs/building_your_site/frontenddevelopers.rst b/docs/building_your_site/frontenddevelopers.rst index 033c64e9e..d39bd8c33 100644 --- a/docs/building_your_site/frontenddevelopers.rst +++ b/docs/building_your_site/frontenddevelopers.rst @@ -19,7 +19,7 @@ Displaying Pages ========================== Template Location ------------------ +~~~~~~~~~~~~~~~~~ For each of your ``Page``-derived models, Wagtail will look for a template in the following location, relative to your project root:: @@ -36,7 +36,7 @@ Class names are converted from camel case to underscores. For example, the templ Self ----- +~~~~ By default, the context passed to a model's template consists of two properties: ``self`` and ``request``. ``self`` is the model object being displayed. ``request`` is the normal Django request object. So, to include the title of a ``Page``, use ``{{ self.title }}``. @@ -45,9 +45,8 @@ Static files (css, js, images) ======================== - Images -~~~~~~~~~~ +~~~~~~ Images uploaded to Wagtail go into the image library and from there are added to pages via the :doc:`page editor interface `. @@ -55,7 +54,7 @@ Unlike other CMS, adding images to a page does not involve choosing a "version" Images from the library **must** be requested using this syntax, but images in your codebase can be added via conventional means e.g ``img`` tags. Only images from the library can be manipulated on the fly. -Read more about the image manipulation syntax here :ref:`Images tag `. +Read more about the image manipulation syntax here :ref:`image_tag`. ======================== @@ -64,7 +63,9 @@ Template tags & filters In addition to Django's standard tags and filters, Wagtail provides some of it's own, which can be ``load``-ed `as you would any other `_ -.. _image-tag: + +.. _image_tag: + Images (tag) ~~~~~~~~~~~~ @@ -123,8 +124,9 @@ The available ``method`` s are: Wagtail *does not allow deforming or stretching images*. Image dimension ratios will always be kept. Wagtail also *does not support upscaling*. Small images forced to appear at larger sizes will "max out" at their their native dimensions. -To request the "original" version of an image, it is suggested you rely on the lack of upscalling support by requesting an image much larger than it's maximum dimensions. e.g to insert an image who's dimensions are uncertain/unknown, at it's maximum size, try: ``{% image self.image width-10000 %}``. This assumes the image is unlikely to be larger than 10000px wide. +To request the "original" version of an image, it is suggested you rely on the lack of upscaling support by requesting an image much larger than it's maximum dimensions. e.g to insert an image who's dimensions are uncertain/unknown, at it's maximum size, try: ``{% image self.image width-10000 %}``. This assumes the image is unlikely to be larger than 10000px wide. +.. _rich-text-filter: Rich text (filter) ~~~~~~~~~~~~~~~~~~ diff --git a/docs/editing_api.rst b/docs/editing_api.rst index 2985a1229..99e859437 100644 --- a/docs/editing_api.rst +++ b/docs/editing_api.rst @@ -27,11 +27,11 @@ There are three types of panels: ``FieldPanel( field_name, classname=None )`` This is the panel used for basic Django field types. ``field_name`` is the name of the class property used in your model definition. ``classname`` is a string of optional CSS classes given to the panel which are used in formatting and scripted interactivity. By default, panels are formatted as inset fields. The CSS class ``full`` can be used to format the panel so it covers the full width of the Wagtail page editor. The CSS class ``title`` can be used to mark a field as the source for auto-generated slug strings. - ``MultiFieldPanel( panel_list, heading )`` + ``MultiFieldPanel( children, heading="", classname=None )`` This panel condenses several ``FieldPanel`` s or choosers, from a list or tuple, under a single ``heading`` string. ``InlinePanel( base_model, relation_name, panels=None, label='', help_text='' )`` - This panel allows for the creation of a "cluster" of related objects over a join to a separate model, such as a list of related links or slides to an image carousel. This is a very powerful, but tricky feature which will take some space to cover, so we'll skip over it for now. For a full explaination on the usage of ``InlinePanel``, see :ref:`inline_panels`. + This panel allows for the creation of a "cluster" of related objects over a join to a separate model, such as a list of related links or slides to an image carousel. This is a very powerful, but tricky feature which will take some space to cover, so we'll skip over it for now. For a full explanation on the usage of ``InlinePanel``, see :ref:`inline_panels`. Wagtail provides a tabbed interface to help organize panels. ``content_panels`` is the main tab, used for the meat of your model content. The other, ``promote_panels``, is suggested for organizing metadata about the content, such as SEO information and other machine-readable information. Since you're writing the panel definitions, you can organize them however you want. @@ -65,8 +65,7 @@ Let's look at an example of a panel definition: MultiFieldPanel(COMMON_PANELS, "Common page configuration"), ] - - +After the ``Page``-derived class definition, just add lists of panel definitions to order and organize the Wagtail page editing interface for your model. Built-in Fields and Choosers @@ -85,100 +84,219 @@ Wagtail provides a general-purpose WYSIWYG editor for creating rich text content .. code-block:: python from wagtail.wagtailcore.fields import RichTextField - ... + from wagtail.wagtailadmin.edit_handlers import FieldPanel + # ... class BookPage(Page): book_text = RichTextField() + BookPage.content_panels = [ + FieldPanel('body', classname="full"), + # ... + ] +``RichTextField`` inherits from Django's basic ``TextField`` field, so you can pass any field parameters into ``RichTextField`` as if using a normal Django field. This field does not need a special panel and can be defined with ``FieldPanel``. -If you're interested in extending the capabilities of the Wagtail editor, See :ref:`extending_wysiwyg`. +However, template output from ``RichTextField`` is special and need to be filtered to preserve embedded content. See :ref:`rich-text-filter`. + +If you're interested in extending the capabilities of the Wagtail WYSIWYG editor (hallo.js), See :ref:`extending_wysiwyg`. Images ------ +One of the features of Wagtail is a unified image library, which you can access in your models through the ``Image`` model and the ``ImageChooserPanel`` chooser. Here's how: + .. code-block:: python from wagtail.wagtailimages.models import Image + from wagtail.wagtailimages.edit_handlers import ImageChooserPanel + # ... + class BookPage(Page): + cover = models.ForeignKey( + 'wagtailimages.Image', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+' + ) + + BookPage.content_panels = [ + ImageChooserPanel('cover'), + # ... + ] - feed_image = models.ForeignKey( - 'wagtailimages.Image', - null=True, - blank=True, - on_delete=models.SET_NULL, - related_name='+' - ) +Django's default behavior is to "cascade" deletions through a ForeignKey relationship, which is probably not what you want happening. This is why the ``null``, ``blank``, and ``on_delete`` parameters should be set to allow for an empty field. (See `Django model field reference (on_delete)`_ ). ``ImageChooserPanel`` takes only one argument: the name of the field. + +.. _Django model field reference (on_delete): https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ForeignKey.on_delete + +Displaying ``Image`` objects in a template requires the use of a template tag. See :ref:`image_tag`. Documents --------- +For files in other formats, Wagtail provides a generic file store through the ``Document`` model: + .. code-block:: python from wagtail.wagtaildocs.models import Document + from wagtail.wagtaildocs.edit_handlers import DocumentChooserPanel + # ... + class BookPage(Page): + book_file = models.ForeignKey( + 'wagtaildocs.Document', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+' + ) - link_document = models.ForeignKey( - 'wagtaildocs.Document', - null=True, - blank=True, - related_name='+' - ) + BookPage.content_panels = [ + DocumentChooserPanel('book_file'), + # ... + ] + +As with images, Wagtail documents should also have the appropriate extra parameters to prevent cascade deletions across a ForeignKey relationship. ``DocumentChooserPanel`` takes only one argument: the name of the field. + +Documents can be used directly in templates without tags or filters. Its properties are: + +.. glossary:: + + ``title`` + The title of the document. + + ``url`` + URL to the file. + + ``created_at`` + The date and time the document was created (DateTime). + + ``filename`` + The filename of the file. + + ``file_extension`` + The extension of the file. + + ``tags`` + A ``TaggableManager`` which keeps track of tags associated with the document (uses the ``django-taggit`` module). Pages and Page-derived Models ----------------------------- +You can explicitly link ``Page``-derived models together using the ``Page`` model and ``PageChooserPanel``. + .. code-block:: python from wagtail.wagtailcore.models import Page + from wagtail.wagtailadmin.edit_handlers import PageChooserPanel + # ... + class BookPage(Page): + publisher = models.ForeignKey( + 'wagtailcore.Page', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+', + ) - page = models.ForeignKey( - 'wagtailcore.Page', - related_name='+', - null=True, - blank=True - ) + BookPage.content_panels = [ + PageChooserPanel('related_page', 'demo.PublisherPage'), + # ... + ] -Can also use more specific models. +``PageChooserPanel`` takes two arguments: a field name and an optional page type. Specifying a page type (in the form of an ``"appname.modelname"`` string) will filter the chooser to display only pages of that type. -Snippets (and Basic Django Models?) +Snippets -------- -Snippets are not not subclasses, so you must include the model class directly. A chooser is provided which takes the snippet class. +Snippets are not subclasses, so you must include the model class directly. A chooser is provided which takes the field name snippet class. .. code-block:: python - advert = models.ForeignKey( - 'demo.Advert', - related_name='+' - ) + from wagtail.wagtailsnippets.edit_handlers import SnippetChooserPanel + # ... + class BookPage(Page): + advert = models.ForeignKey( + 'demo.Advert', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+' + ) + + BookPage.content_panels = [ + SnippetChooserPanel('advert', Advert), + # ... + ] + +See :ref:`snippets` for more information. - - - - - - - - - - - - -PageChooserPanel -~~~~~~~~~~~~~~~~ - -ImageChooserPanel -~~~~~~~~~~~~~~~~~ - -DocumentChooserPanel -~~~~~~~~~~~~~~~~~~~~ - -SnippetChooserPanel +Field Customization ~~~~~~~~~~~~~~~~~~~ +By adding CSS classnames to your panel definitions or adding extra parameters to your field definitions, you can control much of how your fields will display in the Wagtail page editing interface. Wagtail's page editing interface takes much of its behavior from Django's admin, so you may find many options for customization covered there. (See `Django model field reference`_ ). + +.. _Django model field reference:https://docs.djangoproject.com/en/dev/ref/models/fields/ + + +Full-Width Input +---------------- + +Use ``classname="full"`` to make a field (input element) stretch the full width of the Wagtail page editor. This will not work if the field is encapsulated in a ``MultiFieldPanel``, which places its child fields into a formset. + + +Required Fields +--------------- + +To make input or chooser selection manditory for a field, add ``blank=False`` to its model definition. (See `Django model field reference (blank)`_ ). + +.. _Django model field reference (blank): https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.Field.blank + + +Hiding Fields +------------- + +Without a panel definition, a default form field (without label) will be used to represent your fields. If you intend to hide a field on the Wagtail page editor, define the field with ``editable=False`` (See `Django model field reference (editable)`_ ). + +.. _Django model field reference (editable): https://docs.djangoproject.com/en/dev/ref/models/fields/#editable + + + + + + + + + + + + +MultiFieldPanel +~~~~~~~~~~~~~~~ + +.. code-block:: python + + BOOK_FIELD_COLLECTION = [ + ImageChooserPanel('cover'), + DocumentChooserPanel('book_file'), + PageChooserPanel('publisher'), + ] + + BookPage.content_panels = [ + MultiFieldPanel( + BOOK_FIELD_COLLECTION, + heading="Collection of Book Fields", + classname="collapsible collapsed" + ), + # ... + ] + + + + .. _inline_panels: @@ -193,6 +311,8 @@ The ``django-modelcluster`` module allows for streamlined relation of extra mode Extending the WYSIWYG Editor (hallo.js) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Adding hallo.js plugins: +https://github.com/torchbox/wagtail/commit/1ecc215759142e6cafdacb185bbfd3f8e9cd3185 Edit Handler API diff --git a/docs/model_recipes.rst b/docs/model_recipes.rst index db88daf7c..fe8a89e32 100644 --- a/docs/model_recipes.rst +++ b/docs/model_recipes.rst @@ -1,4 +1,6 @@ +.. _model_recipes: + Model Recipes ============= @@ -174,3 +176,24 @@ Here, ``blogs.filter(tags__name=tag)`` invokes a reverse Django queryset filter Iterating through ``self.tags.all`` will display each tag associated with ``self``, while the link(s) back to the index make use of the filter option added to the ``BlogIndexPage`` model. A Django query could also use the ``tagged_items`` related name field to get ``BlogPage`` objects associated with a tag. This is just one possible way of creating a taxonomy for Wagtail objects. With all of the components for a taxonomy available through Wagtail, you should be able to fulfill even the most exotic taxonomic schemes. + + +Custom Page Contexts by Overriding get_context() +------------------------------------------------ + + + +Load Alternate Templates by Overriding get_template() +----------------------------------------------------- + + + +Page Modes +---------- + +get_page_modes +show_as_mode + + + + diff --git a/docs/snippets.rst b/docs/snippets.rst index 14d62b793..a40b57d94 100644 --- a/docs/snippets.rst +++ b/docs/snippets.rst @@ -1,9 +1,12 @@ + +.. _snippets: + Snippets ======== Snippets are pieces of content which do not necessitate a full webpage to render. They could be used for making secondary content, such as headers, footers, and sidebars, editable in the Wagtail admin. Snippets are models which do not inherit the ``Page`` class and are thus not organized into the Wagtail tree, but can still be made editable by assigning panels and identifying the model as a snippet with ``register_snippet()``. -Snippets are not searchable or orderable in the Wagtail admin, so decide carefully if the content type you would want to build into a snippet might be more suited to a page. +Snippets are not search-able or order-able in the Wagtail admin, so decide carefully if the content type you would want to build into a snippet might be more suited to a page. Snippet Models -------------- diff --git a/docs/wagtail_search.rst b/docs/wagtail_search.rst index fff462349..8fa263801 100644 --- a/docs/wagtail_search.rst +++ b/docs/wagtail_search.rst @@ -127,7 +127,7 @@ Lets also add a simple interface for the search with a ```` element to ga
-Finally, we'll use JQuery to make the aynchronous requests and handle the interactivity: +Finally, we'll use JQuery to make the asynchronous requests and handle the interactivity: .. code-block:: guess @@ -186,7 +186,7 @@ Results are returned as a JSON object with this structure: ] } -What if you wanted access to the rest of the results context or didn't feel like using JSON? Wagtail also provides a generalized AJAX interface where you can use your own template to serve results asyncronously. +What if you wanted access to the rest of the results context or didn't feel like using JSON? Wagtail also provides a generalized AJAX interface where you can use your own template to serve results asynchronously. The AJAX interface uses the same view as the normal HTML search, ``wagtailsearch_search``, but will serve different results if Django classifies the request as AJAX (``request.is_ajax()``). Another entry in your project settings will let you override the template used to serve this response: @@ -194,7 +194,7 @@ The AJAX interface uses the same view as the normal HTML search, ``wagtailsearch WAGTAILSEARCH_RESULTS_TEMPLATE_AJAX = 'myapp/includes/search_listing.html' -In this template, you'll have access to the same context variablies provided to the HTML template. You could provide a template in JSON format with extra properties, such as ``query.hits`` and editor's picks, or render an HTML snippet that can go directly into your results ``
``. If you need more flexibility, such as multiple formats/templates based on differing requests, you can set up a custom search view. +In this template, you'll have access to the same context variables provided to the HTML template. You could provide a template in JSON format with extra properties, such as ``query.hits`` and editor's picks, or render an HTML snippet that can go directly into your results ``
``. If you need more flexibility, such as multiple formats/templates based on differing requests, you can set up a custom search view. .. _editors-picks: From fd5f07eb8ab61d718307aed01ba0d096002b13ff Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 27 May 2014 13:29:49 +0100 Subject: [PATCH 55/57] Fixed CSS selector to search form on page chooser fixes #263 --- .../templates/wagtailadmin/chooser/_search_behaviour.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/chooser/_search_behaviour.js b/wagtail/wagtailadmin/templates/wagtailadmin/chooser/_search_behaviour.js index 9c3f77154..a3fee7722 100644 --- a/wagtail/wagtailadmin/templates/wagtailadmin/chooser/_search_behaviour.js +++ b/wagtail/wagtailadmin/templates/wagtailadmin/chooser/_search_behaviour.js @@ -1,6 +1,6 @@ -modal.ajaxifyForm($('form.search-bar', modal.body)); +modal.ajaxifyForm($('form.search-form', modal.body)); -var searchUrl = $('form.search-bar', modal.body).attr('action'); +var searchUrl = $('form.search-form', modal.body).attr('action'); function search() { $.ajax({ From 9ec2c902b5f277f2701f837e27ece23df854bc65 Mon Sep 17 00:00:00 2001 From: Tom Talbot Date: Tue, 27 May 2014 17:06:37 +0100 Subject: [PATCH 56/57] Fix #175. Change to image chooser: 'Upload' tab now retains focus if submit action returns a form error. --- .../templates/wagtailimages/chooser/chooser.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/wagtail/wagtailimages/templates/wagtailimages/chooser/chooser.html b/wagtail/wagtailimages/templates/wagtailimages/chooser/chooser.html index 03b4554c8..1fcadb3f9 100644 --- a/wagtail/wagtailimages/templates/wagtailimages/chooser/chooser.html +++ b/wagtail/wagtailimages/templates/wagtailimages/chooser/chooser.html @@ -5,13 +5,13 @@ {% if uploadform %} {% endif %}
-
{% if uploadform %} -
+
{% csrf_token %}
    From 0393128509558d1dff525acbc63db7b5b86e3d8f Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Wed, 28 May 2014 15:41:40 +0100 Subject: [PATCH 57/57] update changelog / contributors for #267 --- CHANGELOG.txt | 1 + CONTRIBUTORS.rst | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 8b69d346a..27db208fb 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -28,6 +28,7 @@ Changelog * Fix: Moving or changing a site root page no longer causes URLs for subpages to change to 'None' * Fix: Eliminated raw SQL queries from wagtailcore / wagtailadmin, to ensure cross-database compatibility * Fix: Snippets menu item is hidden for administrators if no snippet types are defined + * Fix: 'Upload' tab in image chooser now retains focus if submit action returns a form error. 0.2 (11.03.2014) ~~~~~~~~~~~~~~~~ diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst index 3549e8407..2edc1c079 100644 --- a/CONTRIBUTORS.rst +++ b/CONTRIBUTORS.rst @@ -26,6 +26,7 @@ Contributors * Ben Emery * David Smith * Ben Margolis +* Tom Talbot Translators ===========