copycat 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +12 -2
- data/app/assets/stylesheets/copycat_engine.css +417 -38
- data/app/controllers/copycat_translations_controller.rb +22 -9
- data/app/views/copycat_translations/edit.html.erb +2 -1
- data/app/views/copycat_translations/help.html.erb +25 -0
- data/app/views/copycat_translations/{upload.html.erb → import_export.html.erb} +8 -3
- data/app/views/copycat_translations/index.html.erb +27 -17
- data/app/views/layouts/copycat.html.erb +15 -4
- data/config/routes.rb +6 -3
- data/lib/copycat/version.rb +1 -1
- data/lib/copycat.rb +7 -13
- data/spec/dummy/config/initializers/copycat.rb +2 -2
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/{20120320143433_create_copycat_translations.copycat_engine.rb → 20120320194234_create_copycat_translations.copycat_engine.rb} +0 -0
- data/spec/dummy/db/schema.rb +1 -1
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +5429 -0
- data/spec/dummy/log/test.log +10221 -0
- data/spec/dummy/tmp/cache/assets/C19/060/sprockets%2F125436f53217b7f564aa5016d1168709 +0 -0
- data/spec/dummy/tmp/cache/assets/CB3/6E0/sprockets%2F0f4c96b04436bf7ae900561753947d4c +0 -0
- data/spec/dummy/tmp/cache/assets/DA4/EE0/sprockets%2Fcd39e3d56788faea331e0f5bac67329b +0 -0
- data/spec/dummy/tmp/pids/server.pid +1 -0
- data/spec/factories/copycat_translations.rb +1 -1
- data/spec/integration/copycat_spec.rb +197 -54
- data/spec/integration/dummy_spec.rb +63 -0
- data/spec/spec_helper.rb +1 -0
- metadata +18 -9
- data/app/views/copycat_translations/_copycat_header.html.erb +0 -9
- data/app/views/copycat_translations/readme.html.erb +0 -27
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Copycat #
|
2
2
|
|
3
|
-
Copycat is a Rails engine that allows
|
3
|
+
Copycat is a Rails engine that allows users to edit live website copy.
|
4
4
|
|
5
5
|
## How to use ##
|
6
6
|
|
@@ -13,6 +13,8 @@ rake copycat:install
|
|
13
13
|
rake db:migrate
|
14
14
|
```
|
15
15
|
|
16
|
+
Since Copycat data is stored locally on an indexed table with no foreign keys, page loads are very fast and changes appear instantly.
|
17
|
+
|
16
18
|
In a view, use the Rails i18N.translate() method where you would like to display some editable copy:
|
17
19
|
|
18
20
|
|
@@ -20,7 +22,7 @@ In a view, use the Rails i18N.translate() method where you would like to display
|
|
20
22
|
<h1><%= t('site.index.header') %></h1>
|
21
23
|
```
|
22
24
|
|
23
|
-
Visit the page in your browser, and a Copycat translation will be created for the key. Then visit '/copycat_translations' in your browser and you can edit the value of that token.
|
25
|
+
Visit the page in your browser, and a Copycat translation will be created for the key. Then visit '/copycat_translations' in your browser, log in with the username and password generated in `config/initializers/copycat.rb`, and you can edit the value of that token.
|
24
26
|
|
25
27
|
## Rails i18N API ##
|
26
28
|
|
@@ -28,7 +30,15 @@ You can read about the Rails internationalization framework [here](http://guides
|
|
28
30
|
|
29
31
|
## Deploying ##
|
30
32
|
|
33
|
+
To transfer changes from staging to production:
|
34
|
+
|
35
|
+
* Download copy as YAML on staging
|
36
|
+
* Login to Copycat on production
|
37
|
+
* Upload YAML to production
|
38
|
+
|
39
|
+
Since this process requires no code commits, non-developers can also 'deploy' copy changes.
|
31
40
|
|
41
|
+
You can also commit Copycat's YAML export, which is compatible with i18n, to your git repository.
|
32
42
|
|
33
43
|
## Developing ##
|
34
44
|
|
@@ -1,64 +1,443 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
/*
|
2
|
+
* Skeleton V1.1
|
3
|
+
* Copyright 2011, Dave Gamache
|
4
|
+
* www.getskeleton.com
|
5
|
+
* Free to use under the MIT license.
|
6
|
+
* http://www.opensource.org/licenses/mit-license.php
|
7
|
+
* 8/17/2011
|
8
|
+
*/
|
9
|
+
|
10
|
+
|
11
|
+
/* Table of Content
|
12
|
+
==================================================
|
13
|
+
#Reset & Basics
|
14
|
+
#Basic Styles
|
15
|
+
#Site Styles
|
16
|
+
#Typography
|
17
|
+
#Links
|
18
|
+
#Lists
|
19
|
+
#Images
|
20
|
+
#Buttons
|
21
|
+
#Tabs
|
22
|
+
#Forms
|
23
|
+
#Misc */
|
24
|
+
|
25
|
+
|
26
|
+
/* #Reset & Basics (Inspired by E. Meyers)
|
27
|
+
================================================== */
|
28
|
+
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
|
29
|
+
margin: 0;
|
30
|
+
padding: 0;
|
31
|
+
border: 0;
|
32
|
+
font-size: 100%;
|
33
|
+
font: inherit;
|
34
|
+
vertical-align: baseline; }
|
35
|
+
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
|
36
|
+
display: block; }
|
37
|
+
body {
|
38
|
+
line-height: 1; }
|
39
|
+
ol, ul {
|
40
|
+
list-style: none; }
|
41
|
+
blockquote, q {
|
42
|
+
quotes: none; }
|
43
|
+
blockquote:before, blockquote:after,
|
44
|
+
q:before, q:after {
|
45
|
+
content: '';
|
46
|
+
content: none; }
|
47
|
+
table {
|
48
|
+
border-collapse: collapse;
|
49
|
+
border-spacing: 0; }
|
50
|
+
|
51
|
+
|
52
|
+
/* #Basic Styles
|
53
|
+
================================================== */
|
54
|
+
body {
|
55
|
+
background: #fff;
|
56
|
+
font: 14px/21px "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
57
|
+
color: #444;
|
58
|
+
-webkit-font-smoothing: antialiased; /* Fix for webkit rendering */
|
59
|
+
-webkit-text-size-adjust: 100%;
|
60
|
+
}
|
61
|
+
|
62
|
+
|
63
|
+
/* #Typography
|
64
|
+
================================================== */
|
65
|
+
h1, h2, h3, h4, h5, h6 {
|
66
|
+
color: #181818;
|
67
|
+
font-family: "Georgia", "Times New Roman", Helvetica, Arial, sans-serif;
|
68
|
+
font-weight: normal; }
|
69
|
+
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { font-weight: inherit; }
|
70
|
+
h1 { font-size: 46px; line-height: 50px; margin-bottom: 14px;}
|
71
|
+
h2 { font-size: 35px; line-height: 40px; margin-bottom: 10px; }
|
72
|
+
h3 { font-size: 28px; line-height: 34px; margin-bottom: 8px; }
|
73
|
+
h4 { font-size: 21px; line-height: 30px; margin-bottom: 4px; }
|
74
|
+
h5 { font-size: 17px; line-height: 24px; }
|
75
|
+
h6 { font-size: 14px; line-height: 21px; }
|
76
|
+
.subheader { color: #777; }
|
77
|
+
|
78
|
+
p { margin: 0 0 20px 0; }
|
79
|
+
p img { margin: 0; }
|
80
|
+
p.lead { font-size: 21px; line-height: 27px; color: #777; }
|
81
|
+
|
82
|
+
em { font-style: italic; }
|
83
|
+
strong { font-weight: bold; color: #333; }
|
84
|
+
small { font-size: 80%; }
|
85
|
+
|
86
|
+
/* Blockquotes */
|
87
|
+
blockquote, blockquote p { font-size: 17px; line-height: 24px; color: #777; font-style: italic; }
|
88
|
+
blockquote { margin: 0 0 20px; padding: 9px 20px 0 19px; border-left: 1px solid #ddd; }
|
89
|
+
blockquote cite { display: block; font-size: 12px; color: #555; }
|
90
|
+
blockquote cite:before { content: "\2014 \0020"; }
|
91
|
+
blockquote cite a, blockquote cite a:visited, blockquote cite a:visited { color: #555; }
|
92
|
+
|
93
|
+
hr { border: solid #ddd; border-width: 1px 0 0; clear: both; margin: 10px 0 30px; height: 0; }
|
94
|
+
|
95
|
+
|
96
|
+
/* #Links
|
97
|
+
================================================== */
|
98
|
+
a, a:visited { color: #333; text-decoration: underline; outline: 0; }
|
99
|
+
a:hover, a:focus { color: #000; }
|
100
|
+
p a, p a:visited { line-height: inherit; }
|
101
|
+
|
102
|
+
|
103
|
+
/* #Lists
|
104
|
+
================================================== */
|
105
|
+
ul, ol { margin-bottom: 20px; }
|
106
|
+
ul { list-style: none outside; }
|
107
|
+
ol { list-style: decimal; }
|
108
|
+
ol, ul.square, ul.circle, ul.disc { margin-left: 30px; }
|
109
|
+
ul.square { list-style: square outside; }
|
110
|
+
ul.circle { list-style: circle outside; }
|
111
|
+
ul.disc { list-style: disc outside; }
|
112
|
+
ul ul, ul ol,
|
113
|
+
ol ol, ol ul { margin: 4px 0 5px 30px; font-size: 90%; }
|
114
|
+
ul ul li, ul ol li,
|
115
|
+
ol ol li, ol ul li { margin-bottom: 6px; }
|
116
|
+
li { line-height: 18px; margin-bottom: 12px; }
|
117
|
+
ul.large li { line-height: 21px; }
|
118
|
+
li p { line-height: 21px; }
|
119
|
+
|
120
|
+
/* #Images
|
121
|
+
================================================== */
|
122
|
+
|
123
|
+
img.scale-with-grid {
|
124
|
+
max-width: 100%;
|
125
|
+
height: auto; }
|
126
|
+
|
127
|
+
|
128
|
+
/* #Buttons
|
129
|
+
================================================== */
|
130
|
+
|
131
|
+
.button,
|
132
|
+
button,
|
133
|
+
input[type="submit"],
|
134
|
+
input[type="reset"],
|
135
|
+
input[type="button"] {
|
136
|
+
background: #eee; /* Old browsers */
|
137
|
+
background: #eee -moz-linear-gradient(top, rgba(255,255,255,.2) 0%, rgba(0,0,0,.2) 100%); /* FF3.6+ */
|
138
|
+
background: #eee -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,.2)), color-stop(100%,rgba(0,0,0,.2))); /* Chrome,Safari4+ */
|
139
|
+
background: #eee -webkit-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* Chrome10+,Safari5.1+ */
|
140
|
+
background: #eee -o-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* Opera11.10+ */
|
141
|
+
background: #eee -ms-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* IE10+ */
|
142
|
+
background: #eee linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* W3C */
|
143
|
+
border: 1px solid #aaa;
|
144
|
+
border-top: 1px solid #ccc;
|
145
|
+
border-left: 1px solid #ccc;
|
146
|
+
padding: 4px 12px;
|
147
|
+
-moz-border-radius: 3px;
|
148
|
+
-webkit-border-radius: 3px;
|
149
|
+
border-radius: 3px;
|
150
|
+
color: #444;
|
151
|
+
display: inline-block;
|
152
|
+
font-size: 11px;
|
153
|
+
font-weight: bold;
|
154
|
+
text-decoration: none;
|
155
|
+
text-shadow: 0 1px rgba(255, 255, 255, .75);
|
156
|
+
cursor: pointer;
|
157
|
+
margin-bottom: 20px;
|
158
|
+
line-height: normal;
|
159
|
+
padding: 8px 10px;
|
160
|
+
font-family: "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; }
|
161
|
+
|
162
|
+
.button:hover,
|
163
|
+
button:hover,
|
164
|
+
input[type="submit"]:hover,
|
165
|
+
input[type="reset"]:hover,
|
166
|
+
input[type="button"]:hover {
|
167
|
+
color: #222;
|
168
|
+
background: #ddd; /* Old browsers */
|
169
|
+
background: #ddd -moz-linear-gradient(top, rgba(255,255,255,.3) 0%, rgba(0,0,0,.3) 100%); /* FF3.6+ */
|
170
|
+
background: #ddd -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,.3)), color-stop(100%,rgba(0,0,0,.3))); /* Chrome,Safari4+ */
|
171
|
+
background: #ddd -webkit-linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* Chrome10+,Safari5.1+ */
|
172
|
+
background: #ddd -o-linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* Opera11.10+ */
|
173
|
+
background: #ddd -ms-linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* IE10+ */
|
174
|
+
background: #ddd linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* W3C */
|
175
|
+
border: 1px solid #888;
|
176
|
+
border-top: 1px solid #aaa;
|
177
|
+
border-left: 1px solid #aaa; }
|
178
|
+
|
179
|
+
.button:active,
|
180
|
+
button:active,
|
181
|
+
input[type="submit"]:active,
|
182
|
+
input[type="reset"]:active,
|
183
|
+
input[type="button"]:active {
|
184
|
+
border: 1px solid #666;
|
185
|
+
background: #ccc; /* Old browsers */
|
186
|
+
background: #ccc -moz-linear-gradient(top, rgba(255,255,255,.35) 0%, rgba(10,10,10,.4) 100%); /* FF3.6+ */
|
187
|
+
background: #ccc -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,.35)), color-stop(100%,rgba(10,10,10,.4))); /* Chrome,Safari4+ */
|
188
|
+
background: #ccc -webkit-linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* Chrome10+,Safari5.1+ */
|
189
|
+
background: #ccc -o-linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* Opera11.10+ */
|
190
|
+
background: #ccc -ms-linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* IE10+ */
|
191
|
+
background: #ccc linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* W3C */ }
|
192
|
+
|
193
|
+
.button.full-width,
|
194
|
+
button.full-width,
|
195
|
+
input[type="submit"].full-width,
|
196
|
+
input[type="reset"].full-width,
|
197
|
+
input[type="button"].full-width {
|
198
|
+
width: 100%;
|
199
|
+
padding-left: 0 !important;
|
200
|
+
padding-right: 0 !important;
|
201
|
+
text-align: center; }
|
202
|
+
|
203
|
+
/* Fix for odd Mozilla border & padding issues */
|
204
|
+
button::-moz-focus-inner,
|
205
|
+
input::-moz-focus-inner {
|
206
|
+
border: 0;
|
207
|
+
padding: 0;
|
208
|
+
}
|
209
|
+
|
210
|
+
|
211
|
+
/* #Tabs (activate in tabs.js)
|
212
|
+
================================================== */
|
213
|
+
ul.tabs {
|
214
|
+
display: block;
|
215
|
+
margin: 0 0 20px 0;
|
216
|
+
padding: 0;
|
217
|
+
border-bottom: solid 1px #ddd; }
|
218
|
+
ul.tabs li {
|
219
|
+
display: block;
|
220
|
+
width: auto;
|
221
|
+
height: 30px;
|
222
|
+
padding: 0;
|
223
|
+
float: left;
|
224
|
+
margin-bottom: 0; }
|
225
|
+
ul.tabs li a {
|
226
|
+
display: block;
|
227
|
+
text-decoration: none;
|
228
|
+
width: auto;
|
229
|
+
height: 29px;
|
230
|
+
padding: 0px 20px;
|
231
|
+
line-height: 30px;
|
232
|
+
border: solid 1px #ddd;
|
233
|
+
border-width: 1px 1px 0 0;
|
234
|
+
margin: 0;
|
235
|
+
background: #f5f5f5;
|
236
|
+
font-size: 13px; }
|
237
|
+
ul.tabs li a.active {
|
238
|
+
background: #fff;
|
239
|
+
height: 30px;
|
240
|
+
position: relative;
|
241
|
+
top: -4px;
|
242
|
+
padding-top: 4px;
|
243
|
+
border-left-width: 1px;
|
244
|
+
margin: 0 0 0 -1px;
|
245
|
+
color: #111;
|
246
|
+
-moz-border-radius-topleft: 2px;
|
247
|
+
-webkit-border-top-left-radius: 2px;
|
248
|
+
border-top-left-radius: 2px;
|
249
|
+
-moz-border-radius-topright: 2px;
|
250
|
+
-webkit-border-top-right-radius: 2px;
|
251
|
+
border-top-right-radius: 2px; }
|
252
|
+
ul.tabs li:first-child a.active {
|
253
|
+
margin-left: 0; }
|
254
|
+
ul.tabs li:first-child a {
|
255
|
+
border-width: 1px 1px 0 1px;
|
256
|
+
-moz-border-radius-topleft: 2px;
|
257
|
+
-webkit-border-top-left-radius: 2px;
|
258
|
+
border-top-left-radius: 2px; }
|
259
|
+
ul.tabs li:last-child a {
|
260
|
+
-moz-border-radius-topright: 2px;
|
261
|
+
-webkit-border-top-right-radius: 2px;
|
262
|
+
border-top-right-radius: 2px; }
|
263
|
+
|
264
|
+
ul.tabs-content { margin: 0; display: block; }
|
265
|
+
ul.tabs-content > li { display:none; }
|
266
|
+
ul.tabs-content > li.active { display: block; }
|
267
|
+
|
268
|
+
/* Clearfixing tabs for beautiful stacking */
|
269
|
+
ul.tabs:before,
|
270
|
+
ul.tabs:after {
|
271
|
+
content: '\0020';
|
272
|
+
display: block;
|
273
|
+
overflow: hidden;
|
274
|
+
visibility: hidden;
|
275
|
+
width: 0;
|
276
|
+
height: 0; }
|
277
|
+
ul.tabs:after {
|
278
|
+
clear: both; }
|
279
|
+
ul.tabs {
|
280
|
+
zoom: 1; }
|
281
|
+
|
282
|
+
|
283
|
+
/* #Forms
|
284
|
+
================================================== */
|
285
|
+
|
286
|
+
form {
|
287
|
+
margin-bottom: 20px; }
|
288
|
+
fieldset {
|
289
|
+
margin-bottom: 20px; }
|
290
|
+
input[type="text"],
|
291
|
+
input[type="password"],
|
292
|
+
input[type="email"],
|
293
|
+
textarea,
|
294
|
+
select {
|
295
|
+
border: 1px solid #ccc;
|
296
|
+
padding: 6px 4px;
|
297
|
+
outline: none;
|
298
|
+
-moz-border-radius: 2px;
|
299
|
+
-webkit-border-radius: 2px;
|
300
|
+
border-radius: 2px;
|
301
|
+
font: 13px "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
302
|
+
color: #777;
|
303
|
+
margin: 0;
|
304
|
+
width: 210px;
|
305
|
+
max-width: 100%;
|
306
|
+
display: block;
|
307
|
+
margin-bottom: 20px;
|
308
|
+
background: #fff; }
|
309
|
+
select {
|
310
|
+
padding: 0; }
|
311
|
+
input[type="text"]:focus,
|
312
|
+
input[type="password"]:focus,
|
313
|
+
input[type="email"]:focus,
|
314
|
+
textarea:focus {
|
315
|
+
border: 1px solid #aaa;
|
316
|
+
color: #444;
|
317
|
+
-moz-box-shadow: 0 0 3px rgba(0,0,0,.2);
|
318
|
+
-webkit-box-shadow: 0 0 3px rgba(0,0,0,.2);
|
319
|
+
box-shadow: 0 0 3px rgba(0,0,0,.2); }
|
320
|
+
textarea {
|
321
|
+
min-height: 60px; }
|
322
|
+
label,
|
323
|
+
legend {
|
324
|
+
display: block;
|
325
|
+
font-weight: bold;
|
326
|
+
font-size: 13px; }
|
327
|
+
select {
|
328
|
+
width: 220px; }
|
329
|
+
input[type="checkbox"] {
|
330
|
+
display: inline; }
|
331
|
+
label span,
|
332
|
+
legend span {
|
333
|
+
font-weight: normal;
|
334
|
+
font-size: 13px;
|
335
|
+
color: #444; }
|
336
|
+
|
337
|
+
/* #Misc
|
338
|
+
================================================== */
|
339
|
+
.remove-bottom { margin-bottom: 0 !important; }
|
340
|
+
.half-bottom { margin-bottom: 10px !important; }
|
341
|
+
.add-bottom { margin-bottom: 20px !important; }
|
342
|
+
|
343
|
+
/* end of getskeleton */
|
344
|
+
|
345
|
+
h2 {
|
346
|
+
font-size: 1.8em;
|
3
347
|
}
|
4
|
-
|
5
|
-
|
6
|
-
margin-left: 10.5%;
|
7
|
-
padding-left: 2%;
|
8
|
-
margin-right: 10.5%;
|
9
|
-
padding-right: 2%;
|
10
|
-
}
|
11
|
-
#copycat ul {
|
12
|
-
padding-left: 0;
|
13
|
-
padding-top: 2em;
|
14
|
-
}
|
15
|
-
#copycat li, #copycat li h2 {
|
16
|
-
display: inline;
|
17
|
-
padding-right: 4em;
|
18
|
-
}
|
19
|
-
#copycat table, #copycat form, #copycat div.copycat-alert, #copycat div.copycat-notice, div#readme, div#upload {
|
20
|
-
padding-top: 2em;
|
21
|
-
}
|
22
|
-
#copycat table {
|
348
|
+
|
349
|
+
table {
|
23
350
|
width: 100%;
|
24
351
|
border-bottom: 1px #CCC dotted;
|
352
|
+
padding-top: 2em;
|
25
353
|
padding-bottom: 1em;
|
26
354
|
}
|
27
|
-
|
355
|
+
|
356
|
+
table th {
|
28
357
|
text-align: left;
|
29
358
|
padding-bottom: 1em;
|
30
359
|
}
|
31
|
-
|
360
|
+
|
361
|
+
table tr td {
|
32
362
|
padding-top: 1em;
|
33
363
|
padding-bottom: 1em;
|
34
364
|
border-top: 1px #CCC dotted;
|
35
365
|
}
|
36
|
-
|
366
|
+
|
367
|
+
table tr td.key {
|
37
368
|
width: 20%;
|
38
369
|
margin-right: 5%;
|
39
370
|
vertical-align: top;
|
40
371
|
}
|
41
|
-
|
372
|
+
|
373
|
+
table tr td.value {
|
42
374
|
width: 75%;
|
43
375
|
}
|
44
|
-
|
45
|
-
|
46
|
-
|
376
|
+
|
377
|
+
input[type="text"],
|
378
|
+
textarea,
|
379
|
+
select {
|
380
|
+
display: inline;
|
381
|
+
margin: .2em;
|
47
382
|
}
|
48
|
-
|
49
|
-
|
50
|
-
|
383
|
+
|
384
|
+
select {
|
385
|
+
width: 4em;
|
51
386
|
}
|
52
|
-
|
53
|
-
|
387
|
+
|
388
|
+
div.edit {
|
389
|
+
width: 99%;
|
54
390
|
}
|
55
|
-
|
56
|
-
|
391
|
+
|
392
|
+
div.edit textarea {
|
57
393
|
width: 99%;
|
58
394
|
margin-top: 1em;
|
59
395
|
}
|
60
|
-
|
61
|
-
|
62
|
-
|
396
|
+
|
397
|
+
div.edit a {
|
398
|
+
display: block;
|
399
|
+
margin: -2em 0 0 .5em;
|
400
|
+
}
|
401
|
+
|
402
|
+
body {
|
403
|
+
background-color: #FFFDF9;
|
404
|
+
}
|
405
|
+
|
406
|
+
#page {
|
407
|
+
background-color: #FFFDF7;
|
408
|
+
width: 800px;
|
409
|
+
margin: 0 auto;
|
410
|
+
padding: .5em;
|
411
|
+
}
|
412
|
+
#header {
|
413
|
+
width: 100%;
|
414
|
+
height: 4em;
|
415
|
+
}
|
416
|
+
|
417
|
+
#header h1 {
|
418
|
+
margin-left: 1em;
|
419
|
+
float: left;
|
420
|
+
font-size: 2.5em;
|
421
|
+
line-height: 1em;
|
422
|
+
}
|
423
|
+
|
424
|
+
#header ul {
|
63
425
|
float: right;
|
426
|
+
padding-top: 2%;
|
427
|
+
list-style-type: none;
|
428
|
+
}
|
429
|
+
|
430
|
+
#header li {
|
431
|
+
float: left;
|
432
|
+
}
|
433
|
+
|
434
|
+
#header li a {
|
435
|
+
padding: 0 .5em 0 .5em;
|
436
|
+
}
|
437
|
+
|
438
|
+
#notice {
|
439
|
+
height: 2em;
|
440
|
+
background-color: #FFFFBB;
|
441
|
+
text-align: center;
|
64
442
|
}
|
443
|
+
|
@@ -5,11 +5,20 @@ class CopycatTranslationsController < ApplicationController
|
|
5
5
|
layout 'copycat'
|
6
6
|
|
7
7
|
def index
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
params[:locale] = I18n.default_locale unless params.has_key?(:locale)
|
9
|
+
query = CopycatTranslation
|
10
|
+
query = query.where(locale: params[:locale]) unless params[:locale].blank?
|
11
|
+
|
12
|
+
if params.has_key?(:search)
|
13
|
+
if (search = params[:search]).blank?
|
14
|
+
@copycat_translations = query.all
|
15
|
+
else
|
16
|
+
@copycat_translations = query.where("key LIKE ? OR value LIKE ?", "%#{search}%", "%#{search}%")
|
17
|
+
end
|
18
|
+
else
|
19
|
+
@copycat_translations = []
|
12
20
|
end
|
21
|
+
@locale_names = CopycatTranslation.find(:all, select: 'distinct locale').map(&:locale)
|
13
22
|
end
|
14
23
|
|
15
24
|
def edit
|
@@ -20,7 +29,6 @@ class CopycatTranslationsController < ApplicationController
|
|
20
29
|
cct = CopycatTranslation.find_by_id(params["id"])
|
21
30
|
cct.value = params["copycat_translation"]["value"]
|
22
31
|
if cct.save
|
23
|
-
@copycat_translations = CopycatTranslation.all
|
24
32
|
redirect_to copycat_translations_path
|
25
33
|
else
|
26
34
|
@copycat_translation = cct
|
@@ -28,18 +36,23 @@ class CopycatTranslationsController < ApplicationController
|
|
28
36
|
end
|
29
37
|
end
|
30
38
|
|
31
|
-
def
|
39
|
+
def help
|
32
40
|
end
|
33
41
|
|
34
|
-
def
|
42
|
+
def import_export
|
35
43
|
end
|
36
44
|
|
37
|
-
def
|
45
|
+
def download
|
46
|
+
filename = "copycat_translations_#{Time.now.strftime("%Y_%m_%d_%H_%M_%S")}.yml"
|
47
|
+
send_data CopycatTranslation.export_yaml, :filename => filename
|
48
|
+
end
|
49
|
+
|
50
|
+
def upload
|
38
51
|
begin
|
39
52
|
CopycatTranslation.import_yaml(params["file"].tempfile)
|
40
53
|
rescue StandardError => e
|
41
54
|
flash[:notice] = "There was an error processing your upload!"
|
42
|
-
render :action => '
|
55
|
+
render :action => 'import_export', :status => 400
|
43
56
|
else
|
44
57
|
redirect_to copycat_translations_path, :notice => "YAML file uploaded successfully!"
|
45
58
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<div class="
|
1
|
+
<div class="edit">
|
2
2
|
<%= form_for @copycat_translation, :url => { :action => "update" }, :html => {:class => "copycat_translation"} do |f| %>
|
3
3
|
<span class="copycat-edit-form-key"><%= @copycat_translation.key %></span>
|
4
4
|
<br>
|
@@ -6,4 +6,5 @@
|
|
6
6
|
<br>
|
7
7
|
<%= f.submit "Update" %>
|
8
8
|
<% end %>
|
9
|
+
<%= link_to "Cancel", copycat_translations_path %>
|
9
10
|
</div>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<div>
|
2
|
+
|
3
|
+
<div>
|
4
|
+
<p>Copycat is a Ruby on Rails engine that allows you to edit live website copy.</p>
|
5
|
+
</div>
|
6
|
+
|
7
|
+
<div>
|
8
|
+
<h2> How to use </h2>
|
9
|
+
<p>Search for the copy text you want to edit. If Copycat is currently controlling that content, it will appear when you search. If not, ask a developer to add it to Copycat. You can filter by locale to control what copy is displayed in different languages.</p>
|
10
|
+
<p>Once copy appears, click the left hand side links to edit. Values with keys ending in "_html" will be parsed as literal html, so you can insert tags. All other values are parsed as plain text.</p>
|
11
|
+
</div>
|
12
|
+
|
13
|
+
<div>
|
14
|
+
<h2> Exporting and Importing </h2>
|
15
|
+
<p> Copycat text is data--not code. By default, it is stored in your server's database, and not the codebase that powers your website. Therefore, you may have to download/upload Copycat data to transfer your copy edits between servers, or to safeguard them between database wipes. Copycat exports (and is able to re-import) all of its data in a plaintext format called "YAML."</p>
|
16
|
+
<h4> Exporting </h4>
|
17
|
+
<p>You can get a YAML file of all your copy by clicking "Download" on the Import/Export page.</p>
|
18
|
+
<h4> Importing </h4>
|
19
|
+
<p>You can upload copy to Copycat by uploading a properly formatted YAML file on the Import/Export page. Uploading copy won't delete any entries from Copycat, but it may update them or create new ones. Use this feature to mass-update your copy from between servers -- e.g., make changes to copy on a test server, and then when you're satisfied, download the YAML file and upload it to your production site. Downloading your copy as YAML and then immediately re-uploading it will leave your copy unchanged.</p>
|
20
|
+
<h4> Commiting copy to code </h4>
|
21
|
+
<p>If your copy has reached a stable state and you don't need to update it live anymore, you can download your copy as YAML and include it as part of the Ruby on Rails application underneath your main website. You can then remove Copycat from the application entirely, and the website will still run exactly as before--it interfaces with Ruby on Rails's built-in translation mechanisms in a very unobtrusive way.
|
22
|
+
</div>
|
23
|
+
|
24
|
+
</div>
|
25
|
+
|
@@ -1,11 +1,16 @@
|
|
1
|
-
<
|
1
|
+
<h2>Import</h2>
|
2
|
+
<div>
|
2
3
|
<p>
|
3
4
|
Upload a YAML (.yml) file following <a href="http://guides.rubyonrails.org/i18n.html">I18n conventions</a>.
|
4
5
|
</p>
|
5
|
-
<%= form_tag '
|
6
|
+
<%= form_tag 'upload', :multipart => true, :'accept-charset' => 'UTF-8' do -%>
|
6
7
|
<%= file_field_tag "file" %>
|
7
8
|
<%= submit_tag "Upload" %>
|
8
9
|
<% end %>
|
9
|
-
<div class="copycat-alert"> <%= notice %> </div>
|
10
10
|
</div>
|
11
|
+
<h2>Export</h2>
|
12
|
+
<div>
|
13
|
+
<%= link_to "Download as YAML", download_copycat_translations_path %>
|
14
|
+
</div>
|
15
|
+
|
11
16
|
|
@@ -1,17 +1,27 @@
|
|
1
|
-
<div
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
<%
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
<
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
1
|
+
<div id="search">
|
2
|
+
<%= form_tag copycat_translations_path, :method => :get do -%>
|
3
|
+
<% locale_options = options_for_select([nil] + @locale_names.map{|l| [l,l]}, params[:locale]) %>
|
4
|
+
<%= select_tag 'locale', locale_options %>
|
5
|
+
<%= text_field_tag :search, params[:search], :placeholder => 'Search for keys or values', :size => 40 %>
|
6
|
+
<%= submit_tag 'Search' %>
|
7
|
+
<% end %>
|
8
|
+
</div>
|
9
|
+
|
10
|
+
<% if @copycat_translations.any? %>
|
11
|
+
<table>
|
12
|
+
<tr>
|
13
|
+
<th> Key </th>
|
14
|
+
<th> Value </th>
|
15
|
+
</tr>
|
16
|
+
<% @copycat_translations.each do |t| %>
|
17
|
+
<tr>
|
18
|
+
<td class="key">
|
19
|
+
<%= link_to "#{t.key}", edit_copycat_translation_path(t) %>
|
20
|
+
</td>
|
21
|
+
<td class="value">
|
22
|
+
<%= t.value %>
|
23
|
+
</td>
|
24
|
+
</tr>
|
25
|
+
<% end %>
|
26
|
+
</table>
|
27
|
+
<% end %>
|