I'm making a Jekyll site destinated for GitHub Pages, and pre-testing it on local Windows 8.1 PC with Jekyll 2.5.3, Ruby 2.0.0p598 (2014-11-13) [x64-mingw32] and Gem 2.0.14.
In Jekyll, I have a collection named albums.
Directory structure for _albums is similar to the following:
_albums
foo.md
bar.md
baz.md
Each file has Front Matter containing values such as title, description etc.
In some site page I'm making a Liquid loop such as following:
{% for album in site.albums %}
/* need to get album name here */
{% endfor %}
The question is:
How can I get a bare name for collection item — like foo or bar (without extension, containing folders etc.)
Jekyll documentation says something about name variable, but album variable only has following properties: output, content, path, relative_path, url, collection (and also title and description I set in Front Matter)
album.path has value similar to: d:/repo/<project_name>/_albums/foo.md
A workaround I use for now is:
{% assign album_name = album.path | split:"/" | last | split:"." | first %}
Could you please suggest any better way?
Thank you in advance.
Related
I'm having a bit of trouble with Symfony twig translations, and I hope someone here can clarify.
Say I have a file /templates/general/hello_world.twig , with the contents:
{% trans with {
'%name%': name,
} %}
"Hello %name%"
{% endtrans %}
When I call bin/console translation:update --output-format=yaml fr --force , the output file translations/messages+intl-icu.fr.yaml now contains the contents:
'"Hello %name%"': '__"Hello %name%"'
This is only the case with Twig files - I have other files in translations where they are locale-suffixed, and those are properly translated into french. I'm not clear what has to happen in order to get the translation:update command to recognize that the original content is in English?
I'm not asking how to choose a locale based on the user request. I'm specifically wanting to generate missing translations for contents in my twig templates, and I'd love to have this command available to get me started. The command works a treat for translations actually in the /translations/ folder.
Update 2
// hello.twig
{% trans with {
'%name%': name,
} %}hello_world{% endtrans %}
//messages.en.yaml
hello_world: "Hello %name%"
Im trying to modify records from my wep page using bolt, for lets say an comment section. If someone posts an answer underneath an news item how do i put that info into an record. And if they want to edit their reaction how would I update it.
So i was trying something at this point with the status. My base status is always published.
{{ record.status == draft }} <-- tried this way
{% set record.status == record.status = draft %} <-- tried SET
{% set record.status == record.status = "draft" %} <-- tried adding ""
After my try and error period I went to all the documentation on bolt and twig. But I cant seem to find out how to do this.
So I hope someone knows how to do this, thank you in advance.
short anwser is - you can't modify database records directly from twig.
Twig it's template system (idea is to show data with it) .
To dwhat you want you need to write all this "stuff" by yourself . It can be done (best way is to learn about creating custom modules - but you need to be quite good with OOPHP , symfony components etc. )
I'm having trouble using the salt mine in a pillar to dynamically create a list of hosts based on a grain value match. I don't get any error, I get no output for all hosts. Actually, I can't get any output for mine from the pillar at all even when using the example from the salt docs. I know it isn't an issue with my top file, because I can access all of the other pillar values. My test minion's mine.interval is set to 5. I've refreshed pillar data, and ran mine.update.
Here's an example of my pillar:
mine_functions:
network.ip_addrs: []
grains.item:
- host
- role
My template file that access the mine functions:
#I know this is writing the same list for each match, I'm just doing this for testing and I'll concat the results into a string when I know it works:
{% for host in salt['mine.get']('roles:web', 'grains.items:host', expr_form='grain') | dictsort() %}
serverList= {{ host }}
{% endfor %}
Output from CLI:
salt "server.domain.com" mine.get "*" "*"
server.domain.com:
----------
How do I get this to work? I get no errors, no output, it just runs smoothly, but nothing is written in the file and I get nothing from the command line. My goal here is to be able to dynamically build a list of servers that match a specific grain to set a configuration value in a config template. Am I down the wrong path here, is there a better way?
I'd recommend using mine.get directly in your sls file to get that list of hosts. I don't think there's any need to pass that through pillar data.
#Utah_Dave, thanks so much for the help both here and in IRC.
Posting this as an answer so anyone else searching for this gets a good example...
pillar:
mine_functions:
grains.items: []
template file:
{% set ft_hosts = [] %}
{% for grain_vals in salt['mine.get']('role:ps:ft:True', 'grains.items', expr_form='grain').items() %}
{% do ft_hosts.append(grain_vals[1]['host']) %}
{% endfor %}
ft.ps.server.hosts={{ ft_hosts|join('|') }}
In config.yml, I define my collections like this:
collections:
music:
output: false
dancing:
output: false
The problem is I will have lots of collections and they will clutter my root Jekyll folder.
Is there a way to group all the collections into a folder, named for example, _collections?
So, I would have:
_collections
_dancing
_music
....
This is now possible (I'm running Jekyll 3.7.2, I'm not sure in which version this was implemented).
Here's how to do it: In your _config.yml you can define your collections as well as the folder for your collections. Let's take a look at an example on a client site I'm working on:
collections:
events:
output: true
work:
output: true
jobs:
output: true
cases:
output: true
permalink: /work/:name
collections_dir: pages
The collections_dir: [your_folder_here] will tell Jekyll to look into that folder for collections. My folder structure in development is as follows:
pages/
...
_events/
_work/
_jobs/
_cases/
And in the compiled site it's as follows:
...
events/
jobs/
work/ (contains both "work" and "cases" collections)
One thing also that wasn't asked, but I found to be useful, was that you're able to output different collections into a same folder. In my case I had a client website on which there were two types of work samples: client cases and general examples. We wanted to separate them for better maintenance but also show them in the same folder. To achieve this you can simply define a permalink for the collection. In our case we put permalink for the cases to appear in the work folder (permalink: /work/:name).
Hope this helps!
This is also present in the Jekyll documentation
Answer is no. Your collections folder must be at the root of your root folder.
Even if you name you create a collection in _collections/_music folder, and set it up like this :
collections:
collections/_music folder:
output: true
Jekyll ends up looking for your collection in _collections_music folder (without any slash) because of path sanitize process.
See jekyll code in collection.rb, site.rb and jekyll.rb
This is now possible since this issue was merged.
User configures as:
collections_dir: my_collections
Then we look in my_collections/_pizza for the pizza collection, and my_collections/_lasagna for the lasagna collection.
Nothing prevents you to use subfolders in your collection.
(Note: this is not an answer to your question but a possible workaround)
So as a workaround you could have just one collection: say _arts for example and organize your folders like:
_arts
dancing
music
concerts
.....
to list them separately you can use:
a FrontMatter variable in your files category: dancing when you have a output and check this for a dancing only list for example.
{% for project in site.arts %}
{% if project.category == 'dancing' %}
....
{% endif %}
{% endfor %}
or check the path when you have no output for the collection
{% for project in site.arts %}
{% if project.url contains 'dancing' %}
....
{% endif %}
{% endfor %}
This could slowdown your build if you have hundreds and hundreds of items inside.
In messages.en.yml, I have
confirmed: Congrats %username%, your account is now activated.
But I want to 'bold' username to example ... how can I made this ?
confirmed: Congrats <span class='bold'>%username%</span>, your account is now activated.
Of course I could use two sentence in this example like
first: Congrats
second: , your account ...
and inside twig use the html tag but this seems very dirty.
Update 2
In such cases, I started to use like this:
confirmed: Congrats %start_link%%username%%end_link%, your account is now activated
Since separation of concerns is maintained, this way is strongly recommended.
Update
In YAML, I have used translations like this without any problem:
trans.key: click here to continue
Although translations and design should be kept separated there are always some situations that you must use html tags inside translation files as it is also seen in huge projects like Facebook and Twitter.
In such situations, you can use XLIFF format which is being recommended by Symfony. Inside translation file:
<trans-unit id="1">
<source>confirmed</source>
<target>Congrats <![CDATA[<span class='bold'>%username%</span>]]> , your account is now activated.</target>
</trans-unit>
Twig's Raw Filter
I don't know if this was an option back in 2013 but when using translation, you can apply the raw twig filter having this translation string:
confirmed: Congrats <span class='bold'>%username%</span>,
your account is now activated.
And use it in twig like this:
{{ 'confirmed'|trans|raw }}
This will not escape the html inside the string and will display the username as bold.
Update: I haven't seen the comment the first time, but Rvanlaak had proposed the raw filter solution in the first place.
Security issues
Note that the content of those translation strings must not be user provided, because it could open up your application to XSS attacks. Using the raw filter allows JavaScript to be executed if a malicious user is able to input custom data into the translation strings (Community based translations for example)
Separation of concerns
Using the raw filter does not comply with separation of concerns as the content and styling are bound together. As Ferhad mentioned, using his method, separation of concern will be maintained. But in my case, I preferred using a simple raw filter. I felt that for my case, Ferhad's method was a bit overkill for me, though it would be more recommended his way
My approach is although still ugly, but at least respects the separation of concerns. Escape filter is used to escape a variable, making the final result is pretty safe from XSS, because all other sources considered to be hard-coded.
translations.yml
points: You have %num% points left.
template.html.twig
{% set pointsFormatted = '<span class="points">' ~ num | escape ~ '</span>' %}
{{ 'pages.score.points' | trans({'%num%' : pointsFormatted}) | raw }}
I've just found something out, you can use this in your YAML file:
mind: >
<i>Mind is a nice thing to have</i>
So this ">" sign in the first row achieves it. I think this would be the preferred way, better than handling the escapes etc in TWIG.
I've looked it up now and it is actually a YAML feature. Check here :)
Also, there's an earlier question with similar subject: How can I get YAML to ignore raw HTML in same file.
some yml:
dashboard:
hello: Hello <b>%username%</b>
+
{{ 'dashboard.hello'|trans({'%username%': app.user.username}, 'General') | raw }}
this | raw part worked for me
In my opinion, this is the best solution today:
'key'|trans({'%username%': '<strong>' ~ suspiciousVar|escape ~ '</strong>'})|raw
The only risk here is stored XSS in your translation files.
Holding HTML stuff in translations is wrong, because translators usually break it. But if you really need it:
Twig:
{% trans %}confirmed{% endtrans %}
Yaml translation file:
confirmed: 'Congrats <span class="bold">%username%</span>, your account is now activated.'
Discussion about this:
https://github.com/symfony/symfony/issues/2713
We could use separate twig snippets for different languages if situation requires heavy formatting differences. I wrote a little blog on this.
{# templates/translations/user_message.pl.html.twig #}
{{ 'msg.my_favourite_language_is' }}<b>{{ 'langnames.elfic_language' | trans | lower }}</b>!
{# templates/translations/user_message.en.html.twig #}
{{ 'msg.my_favourite_language_is' }}<i>{{ 'langnames.elfic_language' | trans | ucfirst }}</i>!
{# templates/pages/index.html.twig #}
{% set locale=app.request.locale[:2] %}
{% include 'translations/calculator_message.' ~ locale ~ '.html.twig' %}
Translation files are for translations, design and layout is part of the view layer (namely: template engine (twig)). You can split it into two pieces: congrats and account.activated.